1*5c591343SA. Cody Schuffelen /* Microsoft Reference Implementation for TPM 2.0
2*5c591343SA. Cody Schuffelen *
3*5c591343SA. Cody Schuffelen * The copyright in this software is being made available under the BSD License,
4*5c591343SA. Cody Schuffelen * included below. This software may be subject to other third party and
5*5c591343SA. Cody Schuffelen * contributor rights, including patent rights, and no such rights are granted
6*5c591343SA. Cody Schuffelen * under this license.
7*5c591343SA. Cody Schuffelen *
8*5c591343SA. Cody Schuffelen * Copyright (c) Microsoft Corporation
9*5c591343SA. Cody Schuffelen *
10*5c591343SA. Cody Schuffelen * All rights reserved.
11*5c591343SA. Cody Schuffelen *
12*5c591343SA. Cody Schuffelen * BSD License
13*5c591343SA. Cody Schuffelen *
14*5c591343SA. Cody Schuffelen * Redistribution and use in source and binary forms, with or without modification,
15*5c591343SA. Cody Schuffelen * are permitted provided that the following conditions are met:
16*5c591343SA. Cody Schuffelen *
17*5c591343SA. Cody Schuffelen * Redistributions of source code must retain the above copyright notice, this list
18*5c591343SA. Cody Schuffelen * of conditions and the following disclaimer.
19*5c591343SA. Cody Schuffelen *
20*5c591343SA. Cody Schuffelen * Redistributions in binary form must reproduce the above copyright notice, this
21*5c591343SA. Cody Schuffelen * list of conditions and the following disclaimer in the documentation and/or
22*5c591343SA. Cody Schuffelen * other materials provided with the distribution.
23*5c591343SA. Cody Schuffelen *
24*5c591343SA. Cody Schuffelen * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ""AS IS""
25*5c591343SA. Cody Schuffelen * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26*5c591343SA. Cody Schuffelen * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
27*5c591343SA. Cody Schuffelen * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
28*5c591343SA. Cody Schuffelen * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29*5c591343SA. Cody Schuffelen * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30*5c591343SA. Cody Schuffelen * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
31*5c591343SA. Cody Schuffelen * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
32*5c591343SA. Cody Schuffelen * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
33*5c591343SA. Cody Schuffelen * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34*5c591343SA. Cody Schuffelen */
35*5c591343SA. Cody Schuffelen //** Introduction
36*5c591343SA. Cody Schuffelen
37*5c591343SA. Cody Schuffelen // The NV memory is divided into two areas: dynamic space for user defined NV
38*5c591343SA. Cody Schuffelen // Indices and evict objects, and reserved space for TPM persistent and state save
39*5c591343SA. Cody Schuffelen // data.
40*5c591343SA. Cody Schuffelen //
41*5c591343SA. Cody Schuffelen // The entries in dynamic space are a linked list of entries. Each entry has, as its
42*5c591343SA. Cody Schuffelen // first field, a size. If the size field is zero, it marks the end of the
43*5c591343SA. Cody Schuffelen // list.
44*5c591343SA. Cody Schuffelen //
45*5c591343SA. Cody Schuffelen // An allocation of an Index or evict object may use almost all of the remaining
46*5c591343SA. Cody Schuffelen // NV space such that the size field will not fit. The functions that search the
47*5c591343SA. Cody Schuffelen // list are aware of this and will terminate the search if they either find a zero
48*5c591343SA. Cody Schuffelen // size or recognize that there is insufficient space for the size field.
49*5c591343SA. Cody Schuffelen //
50*5c591343SA. Cody Schuffelen // An Index allocation will contain an NV_INDEX structure. If the Index does not
51*5c591343SA. Cody Schuffelen // have the orderly attribute, the NV_INDEX is followed immediately by the NV data.
52*5c591343SA. Cody Schuffelen //
53*5c591343SA. Cody Schuffelen // An evict object entry contains a handle followed by an OBJECT structure. This
54*5c591343SA. Cody Schuffelen // results in both the Index and Evict Object having an identifying handle as the
55*5c591343SA. Cody Schuffelen // first field following the size field.
56*5c591343SA. Cody Schuffelen //
57*5c591343SA. Cody Schuffelen // When an Index has the orderly attribute, the data is kept in RAM. This RAM is
58*5c591343SA. Cody Schuffelen // saved to backing store in NV memory on any orderly shutdown. The entries in
59*5c591343SA. Cody Schuffelen // orderly memory are also a linked list using a size field as the first entry. As
60*5c591343SA. Cody Schuffelen // with the NV memory, the list is terminated by a zero size field or when the last
61*5c591343SA. Cody Schuffelen // entry leaves insufficient space for the terminating size field.
62*5c591343SA. Cody Schuffelen //
63*5c591343SA. Cody Schuffelen // The attributes of an orderly index are maintained in RAM memory in order to
64*5c591343SA. Cody Schuffelen // reduce the number of NV writes needed for orderly data. When an orderly index
65*5c591343SA. Cody Schuffelen // is created, an entry is made in the dynamic NV memory space that holds the Index
66*5c591343SA. Cody Schuffelen // authorizations (authPolicy and authValue) and the size of the data. This entry is
67*5c591343SA. Cody Schuffelen // only modified if the authValue of the index is changed. The more volatile data
68*5c591343SA. Cody Schuffelen // of the index is kept in RAM. When an orderly Index is created or deleted, the
69*5c591343SA. Cody Schuffelen // RAM data is copied to NV backing store so that the image in the backing store
70*5c591343SA. Cody Schuffelen // matches the layout of RAM. In normal operation. The RAM data is also copied on
71*5c591343SA. Cody Schuffelen // any orderly shutdown. In normal operation, the only other reason for writing
72*5c591343SA. Cody Schuffelen // to the backing store for RAM is when a counter is first written (TPMA_NV_WRITTEN
73*5c591343SA. Cody Schuffelen // changes from CLEAR to SET) or when a counter "rolls over."
74*5c591343SA. Cody Schuffelen //
75*5c591343SA. Cody Schuffelen // Static space contains items that are individually modifiable. The values are in
76*5c591343SA. Cody Schuffelen // the 'gp' PERSISTENT_DATA structure in RAM and mapped to locations in NV.
77*5c591343SA. Cody Schuffelen //
78*5c591343SA. Cody Schuffelen
79*5c591343SA. Cody Schuffelen //** Includes, Defines
80*5c591343SA. Cody Schuffelen #define NV_C
81*5c591343SA. Cody Schuffelen #include "Tpm.h"
82*5c591343SA. Cody Schuffelen
83*5c591343SA. Cody Schuffelen //************************************************
84*5c591343SA. Cody Schuffelen //** Functions
85*5c591343SA. Cody Schuffelen //************************************************
86*5c591343SA. Cody Schuffelen
87*5c591343SA. Cody Schuffelen
88*5c591343SA. Cody Schuffelen //*** NvInitStatic()
89*5c591343SA. Cody Schuffelen // This function initializes the static variables used in the NV subsystem.
90*5c591343SA. Cody Schuffelen static void
NvInitStatic(void)91*5c591343SA. Cody Schuffelen NvInitStatic(
92*5c591343SA. Cody Schuffelen void
93*5c591343SA. Cody Schuffelen )
94*5c591343SA. Cody Schuffelen {
95*5c591343SA. Cody Schuffelen // In some implementations, the end of NV is variable and is set at boot time.
96*5c591343SA. Cody Schuffelen // This value will be the same for each boot, but is not necessarily known
97*5c591343SA. Cody Schuffelen // at compile time.
98*5c591343SA. Cody Schuffelen s_evictNvEnd = (NV_REF)NV_MEMORY_SIZE;
99*5c591343SA. Cody Schuffelen return;
100*5c591343SA. Cody Schuffelen }
101*5c591343SA. Cody Schuffelen
102*5c591343SA. Cody Schuffelen //*** NvCheckState()
103*5c591343SA. Cody Schuffelen // Function to check the NV state by accessing the platform-specific function
104*5c591343SA. Cody Schuffelen // to get the NV state. The result state is registered in s_NvIsAvailable
105*5c591343SA. Cody Schuffelen // that will be reported by NvIsAvailable.
106*5c591343SA. Cody Schuffelen //
107*5c591343SA. Cody Schuffelen // This function is called at the beginning of ExecuteCommand before any potential
108*5c591343SA. Cody Schuffelen // check of g_NvStatus.
109*5c591343SA. Cody Schuffelen void
NvCheckState(void)110*5c591343SA. Cody Schuffelen NvCheckState(
111*5c591343SA. Cody Schuffelen void
112*5c591343SA. Cody Schuffelen )
113*5c591343SA. Cody Schuffelen {
114*5c591343SA. Cody Schuffelen int func_return;
115*5c591343SA. Cody Schuffelen //
116*5c591343SA. Cody Schuffelen func_return = _plat__IsNvAvailable();
117*5c591343SA. Cody Schuffelen if(func_return == 0)
118*5c591343SA. Cody Schuffelen g_NvStatus = TPM_RC_SUCCESS;
119*5c591343SA. Cody Schuffelen else if(func_return == 1)
120*5c591343SA. Cody Schuffelen g_NvStatus = TPM_RC_NV_UNAVAILABLE;
121*5c591343SA. Cody Schuffelen else
122*5c591343SA. Cody Schuffelen g_NvStatus = TPM_RC_NV_RATE;
123*5c591343SA. Cody Schuffelen return;
124*5c591343SA. Cody Schuffelen }
125*5c591343SA. Cody Schuffelen
126*5c591343SA. Cody Schuffelen //*** NvCommit
127*5c591343SA. Cody Schuffelen // This is a wrapper for the platform function to commit pending NV writes.
128*5c591343SA. Cody Schuffelen BOOL
NvCommit(void)129*5c591343SA. Cody Schuffelen NvCommit(
130*5c591343SA. Cody Schuffelen void
131*5c591343SA. Cody Schuffelen )
132*5c591343SA. Cody Schuffelen {
133*5c591343SA. Cody Schuffelen return (_plat__NvCommit() == 0);
134*5c591343SA. Cody Schuffelen }
135*5c591343SA. Cody Schuffelen
136*5c591343SA. Cody Schuffelen //*** NvPowerOn()
137*5c591343SA. Cody Schuffelen // This function is called at _TPM_Init to initialize the NV environment.
138*5c591343SA. Cody Schuffelen // Return Type: BOOL
139*5c591343SA. Cody Schuffelen // TRUE(1) all NV was initialized
140*5c591343SA. Cody Schuffelen // FALSE(0) the NV containing saved state had an error and
141*5c591343SA. Cody Schuffelen // TPM2_Startup(CLEAR) is required
142*5c591343SA. Cody Schuffelen BOOL
NvPowerOn(void)143*5c591343SA. Cody Schuffelen NvPowerOn(
144*5c591343SA. Cody Schuffelen void
145*5c591343SA. Cody Schuffelen )
146*5c591343SA. Cody Schuffelen {
147*5c591343SA. Cody Schuffelen int nvError = 0;
148*5c591343SA. Cody Schuffelen // If power was lost, need to re-establish the RAM data that is loaded from
149*5c591343SA. Cody Schuffelen // NV and initialize the static variables
150*5c591343SA. Cody Schuffelen if(g_powerWasLost)
151*5c591343SA. Cody Schuffelen {
152*5c591343SA. Cody Schuffelen if((nvError = _plat__NVEnable(0)) < 0)
153*5c591343SA. Cody Schuffelen FAIL(FATAL_ERROR_NV_UNRECOVERABLE);
154*5c591343SA. Cody Schuffelen NvInitStatic();
155*5c591343SA. Cody Schuffelen }
156*5c591343SA. Cody Schuffelen return nvError == 0;
157*5c591343SA. Cody Schuffelen }
158*5c591343SA. Cody Schuffelen
159*5c591343SA. Cody Schuffelen //*** NvManufacture()
160*5c591343SA. Cody Schuffelen // This function initializes the NV system at pre-install time.
161*5c591343SA. Cody Schuffelen //
162*5c591343SA. Cody Schuffelen // This function should only be called in a manufacturing environment or in a
163*5c591343SA. Cody Schuffelen // simulation.
164*5c591343SA. Cody Schuffelen //
165*5c591343SA. Cody Schuffelen // The layout of NV memory space is an implementation choice.
166*5c591343SA. Cody Schuffelen void
NvManufacture(void)167*5c591343SA. Cody Schuffelen NvManufacture(
168*5c591343SA. Cody Schuffelen void
169*5c591343SA. Cody Schuffelen )
170*5c591343SA. Cody Schuffelen {
171*5c591343SA. Cody Schuffelen #if SIMULATION
172*5c591343SA. Cody Schuffelen // Simulate the NV memory being in the erased state.
173*5c591343SA. Cody Schuffelen _plat__NvMemoryClear(0, NV_MEMORY_SIZE);
174*5c591343SA. Cody Schuffelen #endif
175*5c591343SA. Cody Schuffelen // Initialize static variables
176*5c591343SA. Cody Schuffelen NvInitStatic();
177*5c591343SA. Cody Schuffelen // Clear the RAM used for Orderly Index data
178*5c591343SA. Cody Schuffelen MemorySet(s_indexOrderlyRam, 0, RAM_INDEX_SPACE);
179*5c591343SA. Cody Schuffelen // Write that Orderly Index data to NV
180*5c591343SA. Cody Schuffelen NvUpdateIndexOrderlyData();
181*5c591343SA. Cody Schuffelen // Initialize the next offset of the first entry in evict/index list to 0 (the
182*5c591343SA. Cody Schuffelen // end of list marker) and the initial s_maxCounterValue;
183*5c591343SA. Cody Schuffelen NvSetMaxCount(0);
184*5c591343SA. Cody Schuffelen // Put the end of list marker at the end of memory. This contains the MaxCount
185*5c591343SA. Cody Schuffelen // value as well as the end marker.
186*5c591343SA. Cody Schuffelen NvWriteNvListEnd(NV_USER_DYNAMIC);
187*5c591343SA. Cody Schuffelen return;
188*5c591343SA. Cody Schuffelen }
189*5c591343SA. Cody Schuffelen
190*5c591343SA. Cody Schuffelen //*** NvRead()
191*5c591343SA. Cody Schuffelen // This function is used to move reserved data from NV memory to RAM.
192*5c591343SA. Cody Schuffelen void
NvRead(void * outBuffer,UINT32 nvOffset,UINT32 size)193*5c591343SA. Cody Schuffelen NvRead(
194*5c591343SA. Cody Schuffelen void *outBuffer, // OUT: buffer to receive data
195*5c591343SA. Cody Schuffelen UINT32 nvOffset, // IN: offset in NV of value
196*5c591343SA. Cody Schuffelen UINT32 size // IN: size of the value to read
197*5c591343SA. Cody Schuffelen )
198*5c591343SA. Cody Schuffelen {
199*5c591343SA. Cody Schuffelen // Input type should be valid
200*5c591343SA. Cody Schuffelen pAssert(nvOffset + size < NV_MEMORY_SIZE);
201*5c591343SA. Cody Schuffelen _plat__NvMemoryRead(nvOffset, size, outBuffer);
202*5c591343SA. Cody Schuffelen return;
203*5c591343SA. Cody Schuffelen }
204*5c591343SA. Cody Schuffelen
205*5c591343SA. Cody Schuffelen //*** NvWrite()
206*5c591343SA. Cody Schuffelen // This function is used to post reserved data for writing to NV memory. Before
207*5c591343SA. Cody Schuffelen // the TPM completes the operation, the value will be written.
208*5c591343SA. Cody Schuffelen BOOL
NvWrite(UINT32 nvOffset,UINT32 size,void * inBuffer)209*5c591343SA. Cody Schuffelen NvWrite(
210*5c591343SA. Cody Schuffelen UINT32 nvOffset, // IN: location in NV to receive data
211*5c591343SA. Cody Schuffelen UINT32 size, // IN: size of the data to move
212*5c591343SA. Cody Schuffelen void *inBuffer // IN: location containing data to write
213*5c591343SA. Cody Schuffelen )
214*5c591343SA. Cody Schuffelen {
215*5c591343SA. Cody Schuffelen // Input type should be valid
216*5c591343SA. Cody Schuffelen if(nvOffset + size <= NV_MEMORY_SIZE)
217*5c591343SA. Cody Schuffelen {
218*5c591343SA. Cody Schuffelen // Set the flag that a NV write happened
219*5c591343SA. Cody Schuffelen SET_NV_UPDATE(UT_NV);
220*5c591343SA. Cody Schuffelen return _plat__NvMemoryWrite(nvOffset, size, inBuffer);
221*5c591343SA. Cody Schuffelen }
222*5c591343SA. Cody Schuffelen return FALSE;
223*5c591343SA. Cody Schuffelen }
224*5c591343SA. Cody Schuffelen
225*5c591343SA. Cody Schuffelen //*** NvUpdatePersistent()
226*5c591343SA. Cody Schuffelen // This function is used to update a value in the PERSISTENT_DATA structure and
227*5c591343SA. Cody Schuffelen // commits the value to NV.
228*5c591343SA. Cody Schuffelen void
NvUpdatePersistent(UINT32 offset,UINT32 size,void * buffer)229*5c591343SA. Cody Schuffelen NvUpdatePersistent(
230*5c591343SA. Cody Schuffelen UINT32 offset, // IN: location in PERMANENT_DATA to be updated
231*5c591343SA. Cody Schuffelen UINT32 size, // IN: size of the value
232*5c591343SA. Cody Schuffelen void *buffer // IN: the new data
233*5c591343SA. Cody Schuffelen )
234*5c591343SA. Cody Schuffelen {
235*5c591343SA. Cody Schuffelen pAssert(offset + size <= sizeof(gp));
236*5c591343SA. Cody Schuffelen MemoryCopy(&gp + offset, buffer, size);
237*5c591343SA. Cody Schuffelen NvWrite(offset, size, buffer);
238*5c591343SA. Cody Schuffelen }
239*5c591343SA. Cody Schuffelen
240*5c591343SA. Cody Schuffelen //*** NvClearPersistent()
241*5c591343SA. Cody Schuffelen // This function is used to clear a persistent data entry and commit it to NV
242*5c591343SA. Cody Schuffelen void
NvClearPersistent(UINT32 offset,UINT32 size)243*5c591343SA. Cody Schuffelen NvClearPersistent(
244*5c591343SA. Cody Schuffelen UINT32 offset, // IN: the offset in the PERMANENT_DATA
245*5c591343SA. Cody Schuffelen // structure to be cleared (zeroed)
246*5c591343SA. Cody Schuffelen UINT32 size // IN: number of bytes to clear
247*5c591343SA. Cody Schuffelen )
248*5c591343SA. Cody Schuffelen {
249*5c591343SA. Cody Schuffelen pAssert(offset + size <= sizeof(gp));
250*5c591343SA. Cody Schuffelen MemorySet((&gp) + offset, 0, size);
251*5c591343SA. Cody Schuffelen NvWrite(offset, size, (&gp) + offset);
252*5c591343SA. Cody Schuffelen }
253*5c591343SA. Cody Schuffelen
254*5c591343SA. Cody Schuffelen //*** NvReadPersistent()
255*5c591343SA. Cody Schuffelen // This function reads persistent data to the RAM copy of the 'gp' structure.
256*5c591343SA. Cody Schuffelen void
NvReadPersistent(void)257*5c591343SA. Cody Schuffelen NvReadPersistent(
258*5c591343SA. Cody Schuffelen void
259*5c591343SA. Cody Schuffelen )
260*5c591343SA. Cody Schuffelen {
261*5c591343SA. Cody Schuffelen NvRead(&gp, NV_PERSISTENT_DATA, sizeof(gp));
262*5c591343SA. Cody Schuffelen return;
263*5c591343SA. Cody Schuffelen }