1 // This file was extracted from the TCG Published 2 // Trusted Platform Module Library 3 // Part 3: Commands 4 // Family "2.0" 5 // Level 00 Revision 01.16 6 // October 30, 2014 7 8 #include "InternalRoutines.h" 9 #include "Shutdown_fp.h" 10 // 11 // 12 // Error Returns Meaning 13 // 14 // TPM_RC_TYPE if PCR bank has been re-configured, a CLEAR StateSave() is 15 // required 16 // 17 TPM_RC 18 TPM2_Shutdown( 19 Shutdown_In *in // IN: input parameter list 20 ) 21 { 22 TPM_RC result; 23 24 // The command needs NV update. Check if NV is available. 25 // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at 26 // this point 27 result = NvIsAvailable(); 28 if(result != TPM_RC_SUCCESS) return result; 29 30 // Input Validation 31 32 // If PCR bank has been reconfigured, a CLEAR state save is required 33 if(g_pcrReConfig && in->shutdownType == TPM_SU_STATE) 34 return TPM_RC_TYPE + RC_Shutdown_shutdownType; 35 36 // Internal Data Update 37 38 // PCR private date state save 39 PCRStateSave(in->shutdownType); 40 41 // Get DRBG state 42 CryptDrbgGetPutState(GET_STATE); 43 44 // Save all orderly data 45 NvWriteReserved(NV_ORDERLY_DATA, &go); 46 47 // Save RAM backed NV index data 48 NvStateSave(); 49 50 if(in->shutdownType == TPM_SU_STATE) 51 { 52 // Save STATE_RESET and STATE_CLEAR data 53 NvWriteReserved(NV_STATE_CLEAR, &gc); 54 NvWriteReserved(NV_STATE_RESET, &gr); 55 } 56 else if(in->shutdownType == TPM_SU_CLEAR) 57 { 58 // Save STATE_RESET data 59 NvWriteReserved(NV_STATE_RESET, &gr); 60 } 61 62 // Write orderly shut down state 63 if(in->shutdownType == TPM_SU_CLEAR) 64 gp.orderlyState = TPM_SU_CLEAR; 65 else if(in->shutdownType == TPM_SU_STATE) 66 { 67 gp.orderlyState = TPM_SU_STATE; 68 // Hack for the H-CRTM and Startup locality settings 69 if(g_DrtmPreStartup) 70 gp.orderlyState |= PRE_STARTUP_FLAG; 71 else if(g_StartupLocality3) 72 gp.orderlyState |= STARTUP_LOCALITY_3; 73 } 74 else 75 pAssert(FALSE); 76 77 NvWriteReserved(NV_ORDERLY, &gp.orderlyState); 78 79 // If PRE_STARTUP_FLAG was SET, then it will stay set in gp.orderlyState even 80 // if the TPM isn't actually shut down. This is OK because all other checks 81 // of gp.orderlyState are to see if it is SHUTDOWN_NONE. So, having 82 // gp.orderlyState set to another value that is also not SHUTDOWN_NONE, is not 83 // an issue. This must be the case, otherwise, it would be impossible to add 84 // an additional shutdown type without major changes to the code. 85 86 return TPM_RC_SUCCESS; 87 } 88