aboutsummaryrefslogtreecommitdiff
path: root/Startup.c
blob: 54df25b487d3057de82696f315b41f36f28362dc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
// This file was extracted from the TCG Published
// Trusted Platform Module Library
// Part 3: Commands
// Family "2.0"
// Level 00 Revision 01.16
// October 30, 2014

#include "InternalRoutines.h"
#include "Startup_fp.h"
#include "Unique_fp.h"
//
//
//     Error Returns                     Meaning
//
//     TPM_RC_LOCALITY                   a Startup(STATE) does not have the same H-CRTM state as the
//                                       previous Startup() or the locality of the startup is not 0 pr 3
//     TPM_RC_NV_UNINITIALIZED           the saved state cannot be recovered and a Startup(CLEAR) is
//                                       requried.
//     TPM_RC_VALUE                      start up type is not compatible with previous shutdown sequence
//
TPM_RC
TPM2_Startup(
   Startup_In        *in                 // IN: input parameter list
   )
{
   STARTUP_TYPE            startup;
   TPM_RC                  result;
   BOOL                    prevDrtmPreStartup;
   BOOL                    prevStartupLoc3;
   BYTE                    locality = _plat__LocalityGet();

   // In the PC Client specification, only locality 0 and 3 are allowed
   if(locality != 0 && locality != 3)
       return TPM_RC_LOCALITY;
   // Indicate that the locality was 3 unless there was an H-CRTM
   if(g_DrtmPreStartup)
       locality = 0;
   g_StartupLocality3 = (locality == 3);

   // The command needs NV update. Check if NV is available.
   // A TPM_RC_NV_UNAVAILABLE or TPM_RC_NV_RATE error may be returned at
   // this point
   result = NvIsAvailable();
   if(result != TPM_RC_SUCCESS)
       return result;
// Input Validation

   // Read orderly shutdown states from previous power cycle
   NvReadReserved(NV_ORDERLY, &g_prevOrderlyState);

   // See if the orderly state indicates that state was saved
   if(     (g_prevOrderlyState & ~(PRE_STARTUP_FLAG | STARTUP_LOCALITY_3))
       == TPM_SU_STATE)
   {
       // If so, extrat the saved flags (HACK)
       prevDrtmPreStartup = (g_prevOrderlyState & PRE_STARTUP_FLAG) != 0;
       prevStartupLoc3 = (g_prevOrderlyState & STARTUP_LOCALITY_3) != 0;
       g_prevOrderlyState = TPM_SU_STATE;
   }
   else
   {
       prevDrtmPreStartup = 0;
       prevStartupLoc3 = 0;
   }
   // if this startup is a TPM Resume, then the H-CRTM states have to match.
   if(in->startupType == TPM_SU_STATE)
  {
         if(g_DrtmPreStartup != prevDrtmPreStartup)
             return TPM_RC_VALUE + RC_Startup_startupType;
         if(g_StartupLocality3 != prevStartupLoc3)
             return TPM_RC_LOCALITY;
  }
  // if the previous power cycle was shut down with no StateSave command, or
  // with StateSave command for CLEAR, or the part of NV used for TPM_SU_STATE
  // cannot be recovered, then this cycle can not startup up with STATE
  if(in->startupType == TPM_SU_STATE)
  {
      if(     g_prevOrderlyState == SHUTDOWN_NONE
         ||   g_prevOrderlyState == TPM_SU_CLEAR)
          return TPM_RC_VALUE + RC_Startup_startupType;

         if(g_nvOk == FALSE)
             return TPM_RC_NV_UNINITIALIZED;
  }

// Internal Date Update

  // Translate the TPM2_ShutDown and TPM2_Startup sequence into the startup
  // types. Will only be a SU_RESTART if the NV is OK
  if(     in->startupType == TPM_SU_CLEAR
      && g_prevOrderlyState == TPM_SU_STATE
      && g_nvOk == TRUE)
  {
      startup = SU_RESTART;
      // Read state reset data
      NvReadReserved(NV_STATE_RESET, &gr);
  }
  // In this check, we don't need to look at g_nvOk because that was checked
  // above
  else if(in->startupType == TPM_SU_STATE && g_prevOrderlyState == TPM_SU_STATE)
  {
      // Read state clear and state reset data
      NvReadReserved(NV_STATE_CLEAR, &gc);
      NvReadReserved(NV_STATE_RESET, &gr);
      startup = SU_RESUME;
  }
  else
  {
      startup = SU_RESET;
  }

  // Read persistent data from NV
  NvReadPersistent();

  // Crypto Startup
  CryptUtilStartup(startup);

  // Read the platform unique value that is used as VENDOR_PERMANENT auth value
  g_platformUniqueDetails.t.size = (UINT16)_plat__GetUnique(1,
                                     sizeof(g_platformUniqueDetails.t.buffer),
                                     g_platformUniqueDetails.t.buffer);

  // Start up subsystems
  // Start counters and timers
  TimeStartup(startup);

  // Start dictionary attack subsystem
  DAStartup(startup);

  // Enable hierarchies
  HierarchyStartup(startup);

   // Restore/Initialize PCR
   PCRStartup(startup, locality);

   // Restore/Initialize command audit information
   CommandAuditStartup(startup);

   // Object context variables
   if(startup == SU_RESET)
   {
       // Reset object context ID to 0
       gr.objectContextID = 0;
       // Reset clearCount to 0
       gr.clearCount= 0;
   }

   // Initialize session table
   SessionStartup(startup);

   // Initialize index/evict data.   This function clear read/write locks
   // in NV index
   NvEntityStartup(startup);

   // Initialize the orderly shut down flag for this cycle to SHUTDOWN_NONE.
   gp.orderlyState = SHUTDOWN_NONE;
   NvWriteReserved(NV_ORDERLY, &gp.orderlyState);

   // Update TPM internal states if command succeeded.
   // Record a TPM2_Startup command has been received.
   TPMRegisterStartup();

   // The H-CRTM state no longer matters
   g_DrtmPreStartup = FALSE;

   if (startup == SU_RESET)
       _plat__ResetCallback();

   return TPM_RC_SUCCESS;
}