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