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 "Startup_fp.h"
10 #include "Unique_fp.h"
11 //
12 //
13 //     Error Returns                     Meaning
14 //
15 //     TPM_RC_LOCALITY                   a Startup(STATE) does not have the same H-CRTM state as the
16 //                                       previous Startup() or the locality of the startup is not 0 pr 3
17 //     TPM_RC_NV_UNINITIALIZED           the saved state cannot be recovered and a Startup(CLEAR) is
18 //                                       requried.
19 //     TPM_RC_VALUE                      start up type is not compatible with previous shutdown sequence
20 //
21 TPM_RC
TPM2_Startup(Startup_In * in)22 TPM2_Startup(
23    Startup_In        *in                 // IN: input parameter list
24    )
25 {
26    STARTUP_TYPE            startup;
27    TPM_RC                  result;
28    BOOL                    prevDrtmPreStartup;
29    BOOL                    prevStartupLoc3;
30    BYTE                    locality = _plat__LocalityGet();
31 
32    // In the PC Client specification, only locality 0 and 3 are allowed
33    if(locality != 0 && locality != 3)
34        return TPM_RC_LOCALITY;
35    // Indicate that the locality was 3 unless there was an H-CRTM
36    if(g_DrtmPreStartup)
37        locality = 0;
38    g_StartupLocality3 = (locality == 3);
39 
40    // The command needs NV update. Check if NV is available.
41    // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
42    // this point
43    result = NvIsAvailable();
44    if(result != TPM_RC_SUCCESS)
45        return result;
46 // Input Validation
47 
48    // Read orderly shutdown states from previous power cycle
49    NvReadReserved(NV_ORDERLY, &g_prevOrderlyState);
50 
51    // See if the orderly state indicates that state was saved
52    if(     (g_prevOrderlyState & ~(PRE_STARTUP_FLAG | STARTUP_LOCALITY_3))
53        == TPM_SU_STATE)
54    {
55        // If so, extrat the saved flags (HACK)
56        prevDrtmPreStartup = (g_prevOrderlyState & PRE_STARTUP_FLAG) != 0;
57        prevStartupLoc3 = (g_prevOrderlyState & STARTUP_LOCALITY_3) != 0;
58        g_prevOrderlyState = TPM_SU_STATE;
59    }
60    else
61    {
62        prevDrtmPreStartup = 0;
63        prevStartupLoc3 = 0;
64    }
65    // if this startup is a TPM Resume, then the H-CRTM states have to match.
66    if(in->startupType == TPM_SU_STATE)
67   {
68          if(g_DrtmPreStartup != prevDrtmPreStartup)
69              return TPM_RC_VALUE + RC_Startup_startupType;
70          if(g_StartupLocality3 != prevStartupLoc3)
71              return TPM_RC_LOCALITY;
72   }
73   // if the previous power cycle was shut down with no StateSave command, or
74   // with StateSave command for CLEAR, or the part of NV used for TPM_SU_STATE
75   // cannot be recovered, then this cycle can not startup up with STATE
76   if(in->startupType == TPM_SU_STATE)
77   {
78       if(     g_prevOrderlyState == SHUTDOWN_NONE
79          ||   g_prevOrderlyState == TPM_SU_CLEAR)
80           return TPM_RC_VALUE + RC_Startup_startupType;
81 
82          if(g_nvOk == FALSE)
83              return TPM_RC_NV_UNINITIALIZED;
84   }
85 
86 // Internal Date Update
87 
88   // Translate the TPM2_ShutDown and TPM2_Startup sequence into the startup
89   // types. Will only be a SU_RESTART if the NV is OK
90   if(     in->startupType == TPM_SU_CLEAR
91       && g_prevOrderlyState == TPM_SU_STATE
92       && g_nvOk == TRUE)
93   {
94       startup = SU_RESTART;
95       // Read state reset data
96       NvReadReserved(NV_STATE_RESET, &gr);
97   }
98   // In this check, we don't need to look at g_nvOk because that was checked
99   // above
100   else if(in->startupType == TPM_SU_STATE && g_prevOrderlyState == TPM_SU_STATE)
101   {
102       // Read state clear and state reset data
103       NvReadReserved(NV_STATE_CLEAR, &gc);
104       NvReadReserved(NV_STATE_RESET, &gr);
105       startup = SU_RESUME;
106   }
107   else
108   {
109       startup = SU_RESET;
110   }
111 
112   // Read persistent data from NV
113   NvReadPersistent();
114 
115   // Crypto Startup
116   CryptUtilStartup(startup);
117 
118   // Read the platform unique value that is used as VENDOR_PERMANENT auth value
119   g_platformUniqueDetails.t.size = (UINT16)_plat__GetUnique(1,
120                                      sizeof(g_platformUniqueDetails.t.buffer),
121                                      g_platformUniqueDetails.t.buffer);
122 
123   // Start up subsystems
124   // Start counters and timers
125   TimeStartup(startup);
126 
127   // Start dictionary attack subsystem
128   DAStartup(startup);
129 
130   // Enable hierarchies
131   HierarchyStartup(startup);
132 
133    // Restore/Initialize PCR
134    PCRStartup(startup, locality);
135 
136    // Restore/Initialize command audit information
137    CommandAuditStartup(startup);
138 
139    // Object context variables
140    if(startup == SU_RESET)
141    {
142        // Reset object context ID to 0
143        gr.objectContextID = 0;
144        // Reset clearCount to 0
145        gr.clearCount= 0;
146    }
147 
148    // Initialize session table
149    SessionStartup(startup);
150 
151    // Initialize index/evict data.   This function clear read/write locks
152    // in NV index
153    NvEntityStartup(startup);
154 
155    // Initialize the orderly shut down flag for this cycle to SHUTDOWN_NONE.
156    gp.orderlyState = SHUTDOWN_NONE;
157    NvWriteReserved(NV_ORDERLY, &gp.orderlyState);
158 
159    // Update TPM internal states if command succeeded.
160    // Record a TPM2_Startup command has been received.
161    TPMRegisterStartup();
162 
163    // The H-CRTM state no longer matters
164    g_DrtmPreStartup = FALSE;
165 
166    return TPM_RC_SUCCESS;
167 }
168