//************************************************************************* //************************************************************************* //** ** //** (C)Copyright 1985-2011, American Megatrends, Inc. ** //** ** //** All Rights Reserved. ** //** ** //** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** //** ** //** Phone: (770)-246-8600 ** //** ** //************************************************************************* //************************************************************************* //********************************************************************** // $Header: /Alaska/SOURCE/Modules/TCG2/Common/TpmClearOnRollback/TpmClearOnRollbackWrapperLib.c 2 4/21/14 3:17p Fredericko $ // // $Revision: 2 $ // // $Date: 4/21/14 3:17p $ //********************************************************************** // Revision History // ---------------- // $Log: /Alaska/SOURCE/Modules/TCG2/Common/TpmClearOnRollback/TpmClearOnRollbackWrapperLib.c $ // // 2 4/21/14 3:17p Fredericko // // 1 4/21/14 2:18p Fredericko // // 1 10/08/13 12:06p Fredericko // Initial Check-In for Tpm-Next module // // 1 7/10/13 5:57p Fredericko // [TAG] EIP120969 // [Category] New Feature // [Description] TCG (TPM20) //********************************************************************** // //--------------------------------------------------------------------------- // Name: // // // //--------------------------------------------------------------------------- // #include "TpmClearOnRollback.h" #include "TpmClearOnRollbackWrapperLib.h" // //---------------------------------------------------------------------------- // Procedure: TpmRecoveryGetFidFromFv // // Description: // Finds FID information in the Flash // // Input: // // // Output: // // //---------------------------------------------------------------------------- // EFI_STATUS TpmRecoveryGetFidFromFv( OUT VOID *Fid ) { static EFI_GUID FidFileName = FID_FFS_FILE_NAME_GUID; EFI_STATUS Status; EFI_HANDLE *FvHandle; UINTN FvCount; UINTN i; UINTN BufferSize; VOID *Buffer; Status = pBS->LocateHandleBuffer(ByProtocol, &gEfiFirmwareVolume2ProtocolGuid, NULL, &FvCount, &FvHandle); if (EFI_ERROR(Status)) return Status; for(i = 0; i < FvCount; i++) { EFI_FIRMWARE_VOLUME_PROTOCOL *Fv; UINT32 AuthStatus; Status = pBS->HandleProtocol(FvHandle[i], &gEfiFirmwareVolume2ProtocolGuid, &Fv); if (EFI_ERROR(Status)) continue; Buffer = 0; BufferSize = 0; Status = Fv->ReadSection(Fv, &FidFileName, EFI_SECTION_FREEFORM_SUBTYPE_GUID, 0, &Buffer, &BufferSize, &AuthStatus); TRACE((-1, "extracted section with guid %g\n", (EFI_GUID *)Buffer)); if (!EFI_ERROR(Status)) { (UINT8 *)Buffer += sizeof(EFI_GUID); MemCpy(Fid, Buffer, sizeof(FW_VERSION)); (UINT8 *)Buffer -= sizeof(EFI_GUID); pBS->FreePool(Buffer); return EFI_SUCCESS; } } pBS->FreePool(FvHandle); return EFI_NOT_FOUND; } // //---------------------------------------------------------------------------- // Procedure: TpmGetFidFromBuffer // // Description: // Finds FID information in provided buffer // // Input: // // // Output: // // //---------------------------------------------------------------------------- // EFI_STATUS TpmGetFidFromBuffer( OUT VOID *Fid, IN VOID *Buffer ) { static EFI_GUID FidSectionGuid = FID_FFS_FILE_SECTION_GUID; UINT32 Signature; UINT32 *SearchPointer; SearchPointer = (UINT32 *)((UINT8 *)Buffer - sizeof(EFI_GUID) + FLASH_SIZE); Signature = FidSectionGuid.Data1; do { if(*SearchPointer == Signature) { if(!guidcmp(&FidSectionGuid, (EFI_GUID *)SearchPointer)) { (UINT8 *)SearchPointer += sizeof(EFI_GUID); MemCpy(Fid, SearchPointer, sizeof(FW_VERSION)); return EFI_SUCCESS; } } } while(SearchPointer-- >= (UINT32 *)Buffer); return EFI_NOT_FOUND; } // //---------------------------------------------------------------------------- // Procedure: SendTpmCommandRecovery // // Description: // Generic send TPM Transaction // // Input: // // // Output: // // //---------------------------------------------------------------------------- // EFI_STATUS SendTpmCommandRecovery(UINT8 *Cmd, UINTN CmdSize, UINT8 *RetBuff, UINTN RetBuffSize) { EFI_STATUS Status; TPM_TRANSMIT_BUFFER InBuffer[1], OutBuffer[1]; InBuffer[0].Buffer = Cmd; InBuffer[0].Size = CmdSize; OutBuffer[0].Buffer = RetBuff; OutBuffer[0].Size = RetBuffSize; Status = TpmLibPassThrough(((TPM_1_2_REGISTERS_PTR)(UINTN)TPM_BASE_ADDRESS), sizeof (InBuffer)/sizeof (*InBuffer), InBuffer, sizeof (OutBuffer) / sizeof (*OutBuffer), OutBuffer); return Status; } //********************************************************************** // // // Procedure: RecoverySetPhysicalPresence // // Description: // // Input: // // Output: // // Modified: // // Referrals: // // Notes: // //********************************************************************** EFI_STATUS RecoverySetPhysicalPresence() { EFI_STATUS Status; PHYSICAL_PRESENCE_CMD PpCmd; TPM_1_2_RET_HEADER retHeader; PpCmd.Hdr.Tag = TPM_H2NS( TPM_TAG_RQU_COMMAND ); PpCmd.Hdr.ParamSize = TPM_H2NL( sizeof (PHYSICAL_PRESENCE_CMD)); PpCmd.Hdr.Ordinal = TPM_H2NL( TSC_ORD_PhysicalPresence ); PpCmd.Data = TPM_H2NS(TPM_PHYSICAL_PRESENCE_CMD_ENABLE ); MemSet(&retHeader, sizeof(TPM_1_2_RET_HEADER), 0); Status = SendTpmCommandRecovery((UINT8 *)&PpCmd, sizeof(PHYSICAL_PRESENCE_CMD), (UINT8 *)&retHeader, sizeof(TPM_1_2_RET_HEADER)); //don't care about error case on setting physical presence CMD type //care about actual physical presence failure MemSet(&retHeader, sizeof(TPM_1_2_RET_HEADER), 0); PpCmd.Data = TPM_H2NS(TPM_PHYSICAL_PRESENCE_PRESENT); Status = SendTpmCommandRecovery((UINT8 *)&PpCmd, sizeof(PHYSICAL_PRESENCE_CMD), (UINT8 *)&retHeader, sizeof(TPM_1_2_RET_HEADER)); if(retHeader.RetCode == 0) { return EFI_SUCCESS; } return EFI_SECURITY_VIOLATION; } //********************************************************************** // // // Procedure: RecoveryEnableActivate // // Description: // // Input: // // Output: // // Modified: // // Referrals: // // Notes: // //********************************************************************** EFI_STATUS RecoveryEnableActivate() { EFI_STATUS Status; DATA_CMD Command; TPM_1_2_CMD_HEADER cmdEnable; TPM_1_2_RET_HEADER retHeader; cmdEnable.Tag = TPM_H2NS( TPM_TAG_RQU_COMMAND ); cmdEnable.ParamSize = TPM_H2NL( sizeof (TPM_1_2_CMD_HEADER)); cmdEnable.Ordinal = TPM_H2NL( TPM_ORD_PhysicalEnable ); MemSet(&retHeader, sizeof(TPM_1_2_RET_HEADER), 0); Status = SendTpmCommandRecovery((UINT8 *)&cmdEnable, sizeof(TPM_1_2_CMD_HEADER), (UINT8 *)&retHeader, sizeof(TPM_1_2_RET_HEADER)); if(!EFI_ERROR(Status) && retHeader.RetCode == 0){ Command.Hdr.Tag = TPM_H2NS( TPM_TAG_RQU_COMMAND ); Command.Hdr.ParamSize = TPM_H2NL( sizeof (DATA_CMD)); Command.Hdr.Ordinal = TPM_H2NL( TPM_ORD_PhysicalSetDeactivated ); Command.Data = 0x0; MemSet(&retHeader, sizeof(TPM_1_2_RET_HEADER), 0); Status = SendTpmCommandRecovery((UINT8 *)&Command, sizeof(DATA_CMD), (UINT8 *)&retHeader, sizeof(TPM_1_2_RET_HEADER)); if(retHeader.RetCode == 0) { return EFI_SUCCESS; } } return EFI_SECURITY_VIOLATION; } //********************************************************************** // // // Procedure: RecoverySendClearCmd // // Description: // // Input: // // Output: // // Modified: // // Referrals: // // Notes: // //********************************************************************** UINT8 RecoverySendClearCmd() { EFI_STATUS Status; TPM_1_2_CMD_HEADER cmdClear; TPM_1_2_RET_HEADER retHeader; cmdClear.Tag = TPM_H2NS( TPM_TAG_RQU_COMMAND ); cmdClear.ParamSize = TPM_H2NL( sizeof (TPM_1_2_CMD_HEADER)); cmdClear.Ordinal = TPM_H2NL( TPM_ORD_ForceClear ); MemSet(&retHeader, sizeof(TPM_1_2_RET_HEADER), 0); Status = SendTpmCommandRecovery((UINT8 *)&cmdClear, sizeof(TPM_1_2_CMD_HEADER), (UINT8 *)&retHeader, sizeof(TPM_1_2_RET_HEADER)); if(retHeader.RetCode == 0) { return TPM_CLEAR_SUCCESSFUL; }else if((retHeader.RetCode == TPM_H2NL(DISABLED))|| (retHeader.RetCode == TPM_H2NL(DEACTIVATED))){ //we need to send enable and activate command //reset and then clear. Status = RecoveryEnableActivate(); if(!EFI_ERROR(Status)){ return TPM_CLEAR_RESET_REQUIRED; } } return TPM_FATAL_CONTINUE_FLASH; } //********************************************************************** // // // Procedure: RecoverySendStartUpCmd // // Description: // // Input: // // Output: // // Modified: // // Referrals: // // Notes: // //********************************************************************** EFI_STATUS RecoverySendStartUpCmd() { EFI_STATUS Status; TPM_1_2_CMD_STARTUP cmdStartup; TPM_1_2_RET_HEADER retHeader; TPM_STARTUP_TYPE TpmSt = TPM_ST_CLEAR; cmdStartup.Header.Tag = TPM_H2NS( TPM_TAG_RQU_COMMAND ); cmdStartup.Header.ParamSize = TPM_H2NL( sizeof (cmdStartup)); cmdStartup.Header.Ordinal = TPM_H2NL( TPM_ORD_Startup ); cmdStartup.StartupType = TPM_H2NS( TpmSt ); MemSet(&retHeader, sizeof(TPM_1_2_RET_HEADER), 0); Status = SendTpmCommandRecovery((UINT8 *)&cmdStartup, sizeof(TPM_1_2_CMD_STARTUP), (UINT8 *)&retHeader, sizeof(TPM_1_2_RET_HEADER)); if(retHeader.RetCode == 0) { return EFI_SUCCESS; } return EFI_DEVICE_ERROR; } //********************************************************************** // // // Procedure: GetCapabilityCmd // // Description: // // Input: // // Output: // // Modified: // // Referrals: // // Notes: // //********************************************************************** EFI_STATUS GetCapabilityCmd(TPM_Capabilities_PermanentFlag *PermFlags) { EFI_STATUS Status = EFI_ABORTED; BOOLEAN Support = FALSE; TPM_GetCapabilities_Input cmdGetCap; cmdGetCap.Tag = TPM_H2NS( TPM_TAG_RQU_COMMAND ); cmdGetCap.ParamSize = TPM_H2NL( sizeof (cmdGetCap)); if(AutoSupportType()){ //not supported return EFI_SUCCESS; }else{ cmdGetCap.CommandCode = TPM_H2NL( TPM_ORD_GetCapability ); cmdGetCap.caparea = TPM_H2NL( TPM_CAP_FLAG ); } cmdGetCap.subCapSize = TPM_H2NL( 4 ); // subCap is always 32bit long cmdGetCap.subCap = TPM_H2NL( TPM_CAP_FLAG_PERMANENT ); Status = SendTpmCommandRecovery((UINT8 *)&cmdGetCap, sizeof(TPM_GetCapabilities_Input), (UINT8 *)PermFlags, sizeof(TPM_Capabilities_PermanentFlag)); if(PermFlags->RetCode == TPM_H2NL(INVALID_POSTINIT)) { return EFI_NOT_READY; } if(PermFlags->RetCode == 0){ return EFI_SUCCESS; } return EFI_DEVICE_ERROR; } //********************************************************************** // // // Procedure: GetVolatileFlags // // Description: // // Input: // // Output: // // Modified: // // Referrals: // // Notes: // //********************************************************************** EFI_STATUS GetVolatileFlags(TPM_VOLATILE_FLAGS *VolatileFlags) { EFI_STATUS Status = EFI_ABORTED; BOOLEAN Support = FALSE; TPM_GetCapabilities_Input cmdGetCap; cmdGetCap.Tag = TPM_H2NS( TPM_TAG_RQU_COMMAND ); cmdGetCap.ParamSize = TPM_H2NL( sizeof (cmdGetCap)); if(AutoSupportType()){ return EFI_SUCCESS; }else{ cmdGetCap.CommandCode = TPM_H2NL( TPM_ORD_GetCapability ); cmdGetCap.caparea = TPM_H2NL( TPM_CAP_FLAG ); } cmdGetCap.subCapSize = TPM_H2NL( 4 ); // subCap is always 32bit long cmdGetCap.subCap = TPM_H2NL( TPM_CAP_FLAG_VOLATILE ); Status = SendTpmCommandRecovery((UINT8 *)&cmdGetCap, sizeof(TPM_GetCapabilities_Input), (UINT8 *)VolatileFlags, sizeof(TPM_VOLATILE_FLAGS)); if(VolatileFlags->RetCode == TPM_H2NL(INVALID_POSTINIT)) { return EFI_NOT_READY; } if(VolatileFlags->RetCode == 0){ return EFI_SUCCESS; } return EFI_DEVICE_ERROR; } //********************************************************************** // // // Procedure: ClearTpmBeforeFlash // // Description: // // Input: // // Output: // // Modified: // // Referrals: // // Notes: // //********************************************************************** UINT8 ClearTpmBeforeFlash() { TPM_Capabilities_PermanentFlag PermFlags; UINT8 Result=0; EFI_STATUS Status; TPM_VOLATILE_FLAGS TpmVolatileFlags; if(AutoSupportType())return TPM_CLEAR_SUCCESSFUL; Status = IsTpmPresent((TPM_1_2_REGISTERS_PTR)( UINTN ) TPM_BASE_ADDRESS); if(EFI_ERROR(Status)){ return TPM_CLEAR_SUCCESSFUL; } //else we have a TPM need to process to clear TisRequestLocality((TPM_1_2_REGISTERS_PTR)( UINTN ) TPM_BASE_ADDRESS); Status = GetCapabilityCmd(&PermFlags); if(Status == EFI_NOT_READY) { Status = RecoverySendStartUpCmd(); if(EFI_ERROR(Status)) { return TPM_FATAL_CONTINUE_FLASH; } } if(EFI_ERROR(Status))return TPM_FATAL_CONTINUE_FLASH; Status = RecoverySetPhysicalPresence(); if(!EFI_ERROR(Status)) { Status = GetVolatileFlags(&TpmVolatileFlags); if(!EFI_ERROR(Status)){ if(TpmVolatileFlags.physicalPresenceLock){ //we need to go into manufacturing mode\special mode //to skip physical presence lock; Return we failed //to clear TPM and flashing should be discontinued. return TPM_FATAL_DISCONTINUE_FLASH; } } Result = RecoverySendClearCmd(); }else{ if(EFI_ERROR(Status))return TPM_FATAL_CONTINUE_FLASH; } TisReleaseLocality((TPM_1_2_REGISTERS_PTR)( UINTN ) TPM_BASE_ADDRESS); return Result; } //************************************************************************* //************************************************************************* //** ** //** (C)Copyright 1985-2010, American Megatrends, Inc. ** //** ** //** All Rights Reserved. ** //** ** //** 5555 Oakbrook Parkway, Suite 200, Norcross, GA 30093 ** //** ** //** Phone: (770)-246-8600 ** //** ** //************************************************************************* //*************************************************************************