// This file was extracted from the TCG Published
// Trusted Platform Module Library
// Part 3: Commands
// Family "2.0"
// Level 00 Revision 01.16
// October 30, 2014
#include "InternalRoutines.h"
#include "Shutdown_fp.h"
//
//
// Error Returns Meaning
//
// TPM_RC_TYPE if PCR bank has been re-configured, a CLEAR StateSave() is
// required
//
TPM_RC
TPM2_Shutdown(
Shutdown_In *in // IN: input parameter list
)
{
TPM_RC result;
// The command needs NV update. Check if NV is available.
// A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
// this point
result = NvIsAvailable();
if(result != TPM_RC_SUCCESS) return result;
// Input Validation
// If PCR bank has been reconfigured, a CLEAR state save is required
if(g_pcrReConfig && in->shutdownType == TPM_SU_STATE)
return TPM_RC_TYPE + RC_Shutdown_shutdownType;
// Internal Data Update
// PCR private date state save
PCRStateSave(in->shutdownType);
// Get DRBG state
CryptDrbgGetPutState(GET_STATE);
// Save all orderly data
NvWriteReserved(NV_ORDERLY_DATA, &go);
// Save RAM backed NV index data
NvStateSave();
if(in->shutdownType == TPM_SU_STATE)
{
// Save STATE_RESET and STATE_CLEAR data
NvWriteReserved(NV_STATE_CLEAR, &gc);
NvWriteReserved(NV_STATE_RESET, &gr);
}
else if(in->shutdownType == TPM_SU_CLEAR)
{
// Save STATE_RESET data
NvWriteReserved(NV_STATE_RESET, &gr);
}
// Write orderly shut down state
if(in->shutdownType == TPM_SU_CLEAR)
gp.orderlyState = TPM_SU_CLEAR;
else if(in->shutdownType == TPM_SU_STATE)
{
gp.orderlyState = TPM_SU_STATE;
// Hack for the H-CRTM and Startup locality settings
if(g_DrtmPreStartup)
gp.orderlyState |= PRE_STARTUP_FLAG;
else if(g_StartupLocality3)
gp.orderlyState |= STARTUP_LOCALITY_3;
}
else
pAssert(FALSE);
NvWriteReserved(NV_ORDERLY, &gp.orderlyState);
// If PRE_STARTUP_FLAG was SET, then it will stay set in gp.orderlyState even
// if the TPM isn't actually shut down. This is OK because all other checks
// of gp.orderlyState are to see if it is SHUTDOWN_NONE. So, having
// gp.orderlyState set to another value that is also not SHUTDOWN_NONE, is not
// an issue. This must be the case, otherwise, it would be impossible to add
// an additional shutdown type without major changes to the code.
return TPM_RC_SUCCESS;
}