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
TPM2_Shutdown(Shutdown_In * in)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