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 #ifdef EMBEDDED_MODE
167 if (startup == SU_RESET)
168 _plat__ResetCallback();
169 #endif
170
171 return TPM_RC_SUCCESS;
172 }
173