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 // indexes 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 Index allocation will contain an NV_INDEX structure. If the Index does not
46*5c591343SA. Cody Schuffelen // have the orderly attribute, the NV_INDEX is followed immediately by the NV data.
47*5c591343SA. Cody Schuffelen //
48*5c591343SA. Cody Schuffelen // An evict object entry contains a handle followed by an OBJECT structure. This
49*5c591343SA. Cody Schuffelen // results in both the Index and Evict Object having an identifying handle as the
50*5c591343SA. Cody Schuffelen // first field following the size field.
51*5c591343SA. Cody Schuffelen //
52*5c591343SA. Cody Schuffelen // When an Index has the orderly attribute, the data is kept in RAM. This RAM is
53*5c591343SA. Cody Schuffelen // saved to backing store in NV memory on any orderly shutdown. The entries in
54*5c591343SA. Cody Schuffelen // orderly memory are also a linked list using a size field as the first entry.
55*5c591343SA. Cody Schuffelen //
56*5c591343SA. Cody Schuffelen // The attributes of an orderly index are maintained in RAM memory in order to
57*5c591343SA. Cody Schuffelen // reduce the number of NV writes needed for orderly data. When an orderly index
58*5c591343SA. Cody Schuffelen // is created, an entry is made in the dynamic NV memory space that holds the Index
59*5c591343SA. Cody Schuffelen // authorizations (authPolicy and authValue) and the size of the data. This entry is
60*5c591343SA. Cody Schuffelen // only modified if the authValue of the index is changed. The more volatile data
61*5c591343SA. Cody Schuffelen // of the index is kept in RAM. When an orderly Index is created or deleted, the
62*5c591343SA. Cody Schuffelen // RAM data is copied to NV backing store so that the image in the backing store
63*5c591343SA. Cody Schuffelen // matches the layout of RAM. In normal operation. The RAM data is also copied on
64*5c591343SA. Cody Schuffelen // any orderly shutdown. In normal operation, the only other reason for writing
65*5c591343SA. Cody Schuffelen // to the backing store for RAM is when a counter is first written (TPMA_NV_WRITTEN
66*5c591343SA. Cody Schuffelen // changes from CLEAR to SET) or when a counter ""rolls over"".
67*5c591343SA. Cody Schuffelen //
68*5c591343SA. Cody Schuffelen // Static space contains items that are individually modifiable. The values are in
69*5c591343SA. Cody Schuffelen // the 'gp' PERSISTENT_DATA structure in RAM and mapped to locations in NV.
70*5c591343SA. Cody Schuffelen //
71*5c591343SA. Cody Schuffelen
72*5c591343SA. Cody Schuffelen //** Includes, Defines and Data Definitions
73*5c591343SA. Cody Schuffelen #define NV_C
74*5c591343SA. Cody Schuffelen #include "Tpm.h"
75*5c591343SA. Cody Schuffelen
76*5c591343SA. Cody Schuffelen //** Local Functions
77*5c591343SA. Cody Schuffelen
78*5c591343SA. Cody Schuffelen
79*5c591343SA. Cody Schuffelen //*** NvNext()
80*5c591343SA. Cody Schuffelen // This function provides a method to traverse every data entry in NV dynamic
81*5c591343SA. Cody Schuffelen // area.
82*5c591343SA. Cody Schuffelen //
83*5c591343SA. Cody Schuffelen // To begin with, parameter 'iter' should be initialized to NV_REF_INIT
84*5c591343SA. Cody Schuffelen // indicating the first element. Every time this function is called, the
85*5c591343SA. Cody Schuffelen // value in 'iter' would be adjusted pointing to the next element in
86*5c591343SA. Cody Schuffelen // traversal. If there is no next element, 'iter' value would be 0.
87*5c591343SA. Cody Schuffelen // This function returns the address of the 'data entry' pointed by the
88*5c591343SA. Cody Schuffelen // 'iter'. If there are no more elements in the set, a 0 value is returned
89*5c591343SA. Cody Schuffelen // indicating the end of traversal.
90*5c591343SA. Cody Schuffelen //
91*5c591343SA. Cody Schuffelen static NV_REF
NvNext(NV_REF * iter,TPM_HANDLE * handle)92*5c591343SA. Cody Schuffelen NvNext(
93*5c591343SA. Cody Schuffelen NV_REF *iter, // IN/OUT: the list iterator
94*5c591343SA. Cody Schuffelen TPM_HANDLE *handle // OUT: the handle of the next item.
95*5c591343SA. Cody Schuffelen )
96*5c591343SA. Cody Schuffelen {
97*5c591343SA. Cody Schuffelen NV_REF currentAddr;
98*5c591343SA. Cody Schuffelen NV_ENTRY_HEADER header;
99*5c591343SA. Cody Schuffelen //
100*5c591343SA. Cody Schuffelen // If iterator is at the beginning of list
101*5c591343SA. Cody Schuffelen if(*iter == NV_REF_INIT)
102*5c591343SA. Cody Schuffelen {
103*5c591343SA. Cody Schuffelen // Initialize iterator
104*5c591343SA. Cody Schuffelen *iter = NV_USER_DYNAMIC;
105*5c591343SA. Cody Schuffelen }
106*5c591343SA. Cody Schuffelen // Step over the size field and point to the handle
107*5c591343SA. Cody Schuffelen currentAddr = *iter + sizeof(UINT32);
108*5c591343SA. Cody Schuffelen
109*5c591343SA. Cody Schuffelen // read the header of the next entry
110*5c591343SA. Cody Schuffelen NvRead(&header, *iter, sizeof(NV_ENTRY_HEADER));
111*5c591343SA. Cody Schuffelen
112*5c591343SA. Cody Schuffelen // if the size field is zero, then we have hit the end of the list
113*5c591343SA. Cody Schuffelen if(header.size == 0)
114*5c591343SA. Cody Schuffelen // leave the *iter pointing at the end of the list
115*5c591343SA. Cody Schuffelen return 0;
116*5c591343SA. Cody Schuffelen // advance the header by the size of the entry
117*5c591343SA. Cody Schuffelen *iter += header.size;
118*5c591343SA. Cody Schuffelen
119*5c591343SA. Cody Schuffelen if(handle != NULL)
120*5c591343SA. Cody Schuffelen *handle = header.handle;
121*5c591343SA. Cody Schuffelen return currentAddr;
122*5c591343SA. Cody Schuffelen }
123*5c591343SA. Cody Schuffelen
124*5c591343SA. Cody Schuffelen
125*5c591343SA. Cody Schuffelen //*** NvNextByType()
126*5c591343SA. Cody Schuffelen // This function returns a reference to the next NV entry of the desired type
127*5c591343SA. Cody Schuffelen // Return Type: NV_REF
128*5c591343SA. Cody Schuffelen // 0 end of list
129*5c591343SA. Cody Schuffelen // != 0 the next entry of the indicated type
130*5c591343SA. Cody Schuffelen static NV_REF
NvNextByType(TPM_HANDLE * handle,NV_REF * iter,TPM_HT type)131*5c591343SA. Cody Schuffelen NvNextByType(
132*5c591343SA. Cody Schuffelen TPM_HANDLE *handle, // OUT: the handle of the found type or 0
133*5c591343SA. Cody Schuffelen NV_REF *iter, // IN: the iterator
134*5c591343SA. Cody Schuffelen TPM_HT type // IN: the handle type to look for
135*5c591343SA. Cody Schuffelen )
136*5c591343SA. Cody Schuffelen {
137*5c591343SA. Cody Schuffelen NV_REF addr;
138*5c591343SA. Cody Schuffelen TPM_HANDLE nvHandle = 0;
139*5c591343SA. Cody Schuffelen //
140*5c591343SA. Cody Schuffelen while((addr = NvNext(iter, &nvHandle)) != 0)
141*5c591343SA. Cody Schuffelen {
142*5c591343SA. Cody Schuffelen // addr: the address of the location containing the handle of the value
143*5c591343SA. Cody Schuffelen // iter: the next location.
144*5c591343SA. Cody Schuffelen if(HandleGetType(nvHandle) == type)
145*5c591343SA. Cody Schuffelen break;
146*5c591343SA. Cody Schuffelen }
147*5c591343SA. Cody Schuffelen if(handle != NULL)
148*5c591343SA. Cody Schuffelen *handle = nvHandle;
149*5c591343SA. Cody Schuffelen return addr;
150*5c591343SA. Cody Schuffelen }
151*5c591343SA. Cody Schuffelen
152*5c591343SA. Cody Schuffelen //*** NvNextIndex()
153*5c591343SA. Cody Schuffelen // This function returns the reference to the next NV Index entry. A value
154*5c591343SA. Cody Schuffelen // of 0 indicates the end of the list.
155*5c591343SA. Cody Schuffelen // Return Type: NV_REF
156*5c591343SA. Cody Schuffelen // 0 end of list
157*5c591343SA. Cody Schuffelen // != 0 the next reference
158*5c591343SA. Cody Schuffelen #define NvNextIndex(handle, iter) \
159*5c591343SA. Cody Schuffelen NvNextByType(handle, iter, TPM_HT_NV_INDEX)
160*5c591343SA. Cody Schuffelen
161*5c591343SA. Cody Schuffelen //*** NvNextEvict()
162*5c591343SA. Cody Schuffelen // This function returns the offset in NV of the next evict object entry. A value
163*5c591343SA. Cody Schuffelen // of 0 indicates the end of the list.
164*5c591343SA. Cody Schuffelen #define NvNextEvict(handle, iter) \
165*5c591343SA. Cody Schuffelen NvNextByType(handle, iter, TPM_HT_PERSISTENT)
166*5c591343SA. Cody Schuffelen
167*5c591343SA. Cody Schuffelen //*** NvGetEnd()
168*5c591343SA. Cody Schuffelen // Function to find the end of the NV dynamic data list
169*5c591343SA. Cody Schuffelen static NV_REF
NvGetEnd(void)170*5c591343SA. Cody Schuffelen NvGetEnd(
171*5c591343SA. Cody Schuffelen void
172*5c591343SA. Cody Schuffelen )
173*5c591343SA. Cody Schuffelen {
174*5c591343SA. Cody Schuffelen NV_REF iter = NV_REF_INIT;
175*5c591343SA. Cody Schuffelen NV_REF currentAddr;
176*5c591343SA. Cody Schuffelen //
177*5c591343SA. Cody Schuffelen // Scan until the next address is 0
178*5c591343SA. Cody Schuffelen while((currentAddr = NvNext(&iter, NULL)) != 0);
179*5c591343SA. Cody Schuffelen return iter;
180*5c591343SA. Cody Schuffelen }
181*5c591343SA. Cody Schuffelen
182*5c591343SA. Cody Schuffelen //*** NvGetFreeBytes
183*5c591343SA. Cody Schuffelen // This function returns the number of free octets in NV space.
184*5c591343SA. Cody Schuffelen static UINT32
NvGetFreeBytes(void)185*5c591343SA. Cody Schuffelen NvGetFreeBytes(
186*5c591343SA. Cody Schuffelen void
187*5c591343SA. Cody Schuffelen )
188*5c591343SA. Cody Schuffelen {
189*5c591343SA. Cody Schuffelen // This does not have an overflow issue because NvGetEnd() cannot return a value
190*5c591343SA. Cody Schuffelen // that is larger than s_evictNvEnd. This is because there is always a 'stop'
191*5c591343SA. Cody Schuffelen // word in the NV memory that terminates the search for the end before the
192*5c591343SA. Cody Schuffelen // value can go past s_evictNvEnd.
193*5c591343SA. Cody Schuffelen return s_evictNvEnd - NvGetEnd();
194*5c591343SA. Cody Schuffelen }
195*5c591343SA. Cody Schuffelen
196*5c591343SA. Cody Schuffelen //*** NvTestSpace()
197*5c591343SA. Cody Schuffelen // This function will test if there is enough space to add a new entity.
198*5c591343SA. Cody Schuffelen // Return Type: BOOL
199*5c591343SA. Cody Schuffelen // TRUE(1) space available
200*5c591343SA. Cody Schuffelen // FALSE(0) no enough space
201*5c591343SA. Cody Schuffelen static BOOL
NvTestSpace(UINT32 size,BOOL isIndex,BOOL isCounter)202*5c591343SA. Cody Schuffelen NvTestSpace(
203*5c591343SA. Cody Schuffelen UINT32 size, // IN: size of the entity to be added
204*5c591343SA. Cody Schuffelen BOOL isIndex, // IN: TRUE if the entity is an index
205*5c591343SA. Cody Schuffelen BOOL isCounter // IN: TRUE if the index is a counter
206*5c591343SA. Cody Schuffelen )
207*5c591343SA. Cody Schuffelen {
208*5c591343SA. Cody Schuffelen UINT32 remainBytes = NvGetFreeBytes();
209*5c591343SA. Cody Schuffelen UINT32 reserved = sizeof(UINT32) // size of the forward pointer
210*5c591343SA. Cody Schuffelen + sizeof(NV_LIST_TERMINATOR);
211*5c591343SA. Cody Schuffelen //
212*5c591343SA. Cody Schuffelen // Do a compile time sanity check on the setting for NV_MEMORY_SIZE
213*5c591343SA. Cody Schuffelen #if NV_MEMORY_SIZE < 1024
214*5c591343SA. Cody Schuffelen #error "NV_MEMORY_SIZE probably isn't large enough"
215*5c591343SA. Cody Schuffelen #endif
216*5c591343SA. Cody Schuffelen
217*5c591343SA. Cody Schuffelen // For NV Index, need to make sure that we do not allocate an Index if this
218*5c591343SA. Cody Schuffelen // would mean that the TPM cannot allocate the minimum number of evict
219*5c591343SA. Cody Schuffelen // objects.
220*5c591343SA. Cody Schuffelen if(isIndex)
221*5c591343SA. Cody Schuffelen {
222*5c591343SA. Cody Schuffelen // Get the number of persistent objects allocated
223*5c591343SA. Cody Schuffelen UINT32 persistentNum = NvCapGetPersistentNumber();
224*5c591343SA. Cody Schuffelen
225*5c591343SA. Cody Schuffelen // If we have not allocated the requisite number of evict objects, then we
226*5c591343SA. Cody Schuffelen // need to reserve space for them.
227*5c591343SA. Cody Schuffelen // NOTE: some of this is not written as simply as it might seem because
228*5c591343SA. Cody Schuffelen // the values are all unsigned and subtracting needs to be done carefully
229*5c591343SA. Cody Schuffelen // so that an underflow doesn't cause problems.
230*5c591343SA. Cody Schuffelen if(persistentNum < MIN_EVICT_OBJECTS)
231*5c591343SA. Cody Schuffelen reserved += (MIN_EVICT_OBJECTS - persistentNum) * NV_EVICT_OBJECT_SIZE;
232*5c591343SA. Cody Schuffelen }
233*5c591343SA. Cody Schuffelen // If this is not an index or is not a counter, reserve space for the
234*5c591343SA. Cody Schuffelen // required number of counter indexes
235*5c591343SA. Cody Schuffelen if(!isIndex || !isCounter)
236*5c591343SA. Cody Schuffelen {
237*5c591343SA. Cody Schuffelen // Get the number of counters
238*5c591343SA. Cody Schuffelen UINT32 counterNum = NvCapGetCounterNumber();
239*5c591343SA. Cody Schuffelen
240*5c591343SA. Cody Schuffelen // If the required number of counters have not been allocated, reserved
241*5c591343SA. Cody Schuffelen // space for the extra needed counters
242*5c591343SA. Cody Schuffelen if(counterNum < MIN_COUNTER_INDICES)
243*5c591343SA. Cody Schuffelen reserved += (MIN_COUNTER_INDICES - counterNum) * NV_INDEX_COUNTER_SIZE;
244*5c591343SA. Cody Schuffelen }
245*5c591343SA. Cody Schuffelen // Check that the requested allocation will fit after making sure that there
246*5c591343SA. Cody Schuffelen // will be no chance of overflow
247*5c591343SA. Cody Schuffelen return ((reserved < remainBytes)
248*5c591343SA. Cody Schuffelen && (size <= remainBytes)
249*5c591343SA. Cody Schuffelen && (size + reserved <= remainBytes));
250*5c591343SA. Cody Schuffelen }
251*5c591343SA. Cody Schuffelen
252*5c591343SA. Cody Schuffelen //*** NvWriteNvListEnd()
253*5c591343SA. Cody Schuffelen // Function to write the list terminator.
254*5c591343SA. Cody Schuffelen NV_REF
NvWriteNvListEnd(NV_REF end)255*5c591343SA. Cody Schuffelen NvWriteNvListEnd(
256*5c591343SA. Cody Schuffelen NV_REF end
257*5c591343SA. Cody Schuffelen )
258*5c591343SA. Cody Schuffelen {
259*5c591343SA. Cody Schuffelen // Marker is initialized with zeros
260*5c591343SA. Cody Schuffelen BYTE listEndMarker[sizeof(NV_LIST_TERMINATOR)] = {0};
261*5c591343SA. Cody Schuffelen UINT64 maxCount = NvReadMaxCount();
262*5c591343SA. Cody Schuffelen //
263*5c591343SA. Cody Schuffelen // This is a constant check that can be resolved at compile time.
264*5c591343SA. Cody Schuffelen cAssert(sizeof(UINT64) <= sizeof(NV_LIST_TERMINATOR) - sizeof(UINT32));
265*5c591343SA. Cody Schuffelen
266*5c591343SA. Cody Schuffelen // Copy the maxCount value to the marker buffer
267*5c591343SA. Cody Schuffelen MemoryCopy(&listEndMarker[sizeof(UINT32)], &maxCount, sizeof(UINT64));
268*5c591343SA. Cody Schuffelen pAssert(end + sizeof(NV_LIST_TERMINATOR) <= s_evictNvEnd);
269*5c591343SA. Cody Schuffelen
270*5c591343SA. Cody Schuffelen // Write it to memory
271*5c591343SA. Cody Schuffelen NvWrite(end, sizeof(NV_LIST_TERMINATOR), &listEndMarker);
272*5c591343SA. Cody Schuffelen return end + sizeof(NV_LIST_TERMINATOR);
273*5c591343SA. Cody Schuffelen }
274*5c591343SA. Cody Schuffelen
275*5c591343SA. Cody Schuffelen
276*5c591343SA. Cody Schuffelen //*** NvAdd()
277*5c591343SA. Cody Schuffelen // This function adds a new entity to NV.
278*5c591343SA. Cody Schuffelen //
279*5c591343SA. Cody Schuffelen // This function requires that there is enough space to add a new entity (i.e.,
280*5c591343SA. Cody Schuffelen // that NvTestSpace() has been called and the available space is at least as
281*5c591343SA. Cody Schuffelen // large as the required space).
282*5c591343SA. Cody Schuffelen //
283*5c591343SA. Cody Schuffelen // The 'totalSize' will be the size of 'entity'. If a handle is added, this
284*5c591343SA. Cody Schuffelen // function will increase the size accordingly.
285*5c591343SA. Cody Schuffelen static TPM_RC
NvAdd(UINT32 totalSize,UINT32 bufferSize,TPM_HANDLE handle,BYTE * entity)286*5c591343SA. Cody Schuffelen NvAdd(
287*5c591343SA. Cody Schuffelen UINT32 totalSize, // IN: total size needed for this entity For
288*5c591343SA. Cody Schuffelen // evict object, totalSize is the same as
289*5c591343SA. Cody Schuffelen // bufferSize. For NV Index, totalSize is
290*5c591343SA. Cody Schuffelen // bufferSize plus index data size
291*5c591343SA. Cody Schuffelen UINT32 bufferSize, // IN: size of initial buffer
292*5c591343SA. Cody Schuffelen TPM_HANDLE handle, // IN: optional handle
293*5c591343SA. Cody Schuffelen BYTE *entity // IN: initial buffer
294*5c591343SA. Cody Schuffelen )
295*5c591343SA. Cody Schuffelen {
296*5c591343SA. Cody Schuffelen NV_REF newAddr; // IN: where the new entity will start
297*5c591343SA. Cody Schuffelen NV_REF nextAddr;
298*5c591343SA. Cody Schuffelen //
299*5c591343SA. Cody Schuffelen RETURN_IF_NV_IS_NOT_AVAILABLE;
300*5c591343SA. Cody Schuffelen
301*5c591343SA. Cody Schuffelen // Get the end of data list
302*5c591343SA. Cody Schuffelen newAddr = NvGetEnd();
303*5c591343SA. Cody Schuffelen
304*5c591343SA. Cody Schuffelen // Step over the forward pointer
305*5c591343SA. Cody Schuffelen nextAddr = newAddr + sizeof(UINT32);
306*5c591343SA. Cody Schuffelen
307*5c591343SA. Cody Schuffelen // Optionally write the handle. For indexes, the handle is TPM_RH_UNASSIGNED
308*5c591343SA. Cody Schuffelen // so that the handle in the nvIndex is used instead of writing this value
309*5c591343SA. Cody Schuffelen if(handle != TPM_RH_UNASSIGNED)
310*5c591343SA. Cody Schuffelen {
311*5c591343SA. Cody Schuffelen NvWrite((UINT32)nextAddr, sizeof(TPM_HANDLE), &handle);
312*5c591343SA. Cody Schuffelen nextAddr += sizeof(TPM_HANDLE);
313*5c591343SA. Cody Schuffelen }
314*5c591343SA. Cody Schuffelen // Write entity data
315*5c591343SA. Cody Schuffelen NvWrite((UINT32)nextAddr, bufferSize, entity);
316*5c591343SA. Cody Schuffelen
317*5c591343SA. Cody Schuffelen // Advance the pointer by the amount of the total
318*5c591343SA. Cody Schuffelen nextAddr += totalSize;
319*5c591343SA. Cody Schuffelen
320*5c591343SA. Cody Schuffelen // Finish by writing the link value
321*5c591343SA. Cody Schuffelen
322*5c591343SA. Cody Schuffelen // Write the next offset (relative addressing)
323*5c591343SA. Cody Schuffelen totalSize = nextAddr - newAddr;
324*5c591343SA. Cody Schuffelen
325*5c591343SA. Cody Schuffelen // Write link value
326*5c591343SA. Cody Schuffelen NvWrite((UINT32)newAddr, sizeof(UINT32), &totalSize);
327*5c591343SA. Cody Schuffelen
328*5c591343SA. Cody Schuffelen // Write the list terminator
329*5c591343SA. Cody Schuffelen NvWriteNvListEnd(nextAddr);
330*5c591343SA. Cody Schuffelen
331*5c591343SA. Cody Schuffelen return TPM_RC_SUCCESS;
332*5c591343SA. Cody Schuffelen }
333*5c591343SA. Cody Schuffelen
334*5c591343SA. Cody Schuffelen //*** NvDelete()
335*5c591343SA. Cody Schuffelen // This function is used to delete an NV Index or persistent object from NV memory.
336*5c591343SA. Cody Schuffelen static TPM_RC
NvDelete(NV_REF entityRef)337*5c591343SA. Cody Schuffelen NvDelete(
338*5c591343SA. Cody Schuffelen NV_REF entityRef // IN: reference to entity to be deleted
339*5c591343SA. Cody Schuffelen )
340*5c591343SA. Cody Schuffelen {
341*5c591343SA. Cody Schuffelen UINT32 entrySize;
342*5c591343SA. Cody Schuffelen // adjust entityAddr to back up and point to the forward pointer
343*5c591343SA. Cody Schuffelen NV_REF entryRef = entityRef - sizeof(UINT32);
344*5c591343SA. Cody Schuffelen NV_REF endRef = NvGetEnd();
345*5c591343SA. Cody Schuffelen NV_REF nextAddr; // address of the next entry
346*5c591343SA. Cody Schuffelen //
347*5c591343SA. Cody Schuffelen RETURN_IF_NV_IS_NOT_AVAILABLE;
348*5c591343SA. Cody Schuffelen
349*5c591343SA. Cody Schuffelen // Get the offset of the next entry. That is, back up and point to the size
350*5c591343SA. Cody Schuffelen // field of the entry
351*5c591343SA. Cody Schuffelen NvRead(&entrySize, entryRef, sizeof(UINT32));
352*5c591343SA. Cody Schuffelen
353*5c591343SA. Cody Schuffelen // The next entry after the one being deleted is at a relative offset
354*5c591343SA. Cody Schuffelen // from the current entry
355*5c591343SA. Cody Schuffelen nextAddr = entryRef + entrySize;
356*5c591343SA. Cody Schuffelen
357*5c591343SA. Cody Schuffelen // If this is not the last entry, move everything up
358*5c591343SA. Cody Schuffelen if(nextAddr < endRef)
359*5c591343SA. Cody Schuffelen {
360*5c591343SA. Cody Schuffelen pAssert(nextAddr > entryRef);
361*5c591343SA. Cody Schuffelen _plat__NvMemoryMove(nextAddr,
362*5c591343SA. Cody Schuffelen entryRef,
363*5c591343SA. Cody Schuffelen (endRef - nextAddr));
364*5c591343SA. Cody Schuffelen }
365*5c591343SA. Cody Schuffelen // The end of the used space is now moved up by the amount of space we just
366*5c591343SA. Cody Schuffelen // reclaimed
367*5c591343SA. Cody Schuffelen endRef -= entrySize;
368*5c591343SA. Cody Schuffelen
369*5c591343SA. Cody Schuffelen // Write the end marker, and make the new end equal to the first byte after
370*5c591343SA. Cody Schuffelen // the just added end value. This will automatically update the NV value for
371*5c591343SA. Cody Schuffelen // maxCounter.
372*5c591343SA. Cody Schuffelen // NOTE: This is the call that sets flag to cause NV to be updated
373*5c591343SA. Cody Schuffelen endRef = NvWriteNvListEnd(endRef);
374*5c591343SA. Cody Schuffelen
375*5c591343SA. Cody Schuffelen // Clear the reclaimed memory
376*5c591343SA. Cody Schuffelen _plat__NvMemoryClear(endRef, entrySize);
377*5c591343SA. Cody Schuffelen
378*5c591343SA. Cody Schuffelen return TPM_RC_SUCCESS;
379*5c591343SA. Cody Schuffelen }
380*5c591343SA. Cody Schuffelen
381*5c591343SA. Cody Schuffelen //************************************************
382*5c591343SA. Cody Schuffelen //** RAM-based NV Index Data Access Functions
383*5c591343SA. Cody Schuffelen //************************************************
384*5c591343SA. Cody Schuffelen //*** Introduction
385*5c591343SA. Cody Schuffelen // The data layout in ram buffer is {size of(NV_handle + attributes + data
386*5c591343SA. Cody Schuffelen // NV_handle, attributes, data}
387*5c591343SA. Cody Schuffelen // for each NV Index data stored in RAM.
388*5c591343SA. Cody Schuffelen //
389*5c591343SA. Cody Schuffelen // NV storage associated with orderly data is updated when a NV Index is added
390*5c591343SA. Cody Schuffelen // but NOT when the data or attributes are changed. Orderly data is only updated
391*5c591343SA. Cody Schuffelen // to NV on an orderly shutdown (TPM2_Shutdown())
392*5c591343SA. Cody Schuffelen
393*5c591343SA. Cody Schuffelen //*** NvRamNext()
394*5c591343SA. Cody Schuffelen // This function is used to iterate trough the list of Ram Index values. *iter needs
395*5c591343SA. Cody Schuffelen // to be initialized by calling
396*5c591343SA. Cody Schuffelen static NV_RAM_REF
NvRamNext(NV_RAM_REF * iter,TPM_HANDLE * handle)397*5c591343SA. Cody Schuffelen NvRamNext(
398*5c591343SA. Cody Schuffelen NV_RAM_REF *iter, // IN/OUT: the list iterator
399*5c591343SA. Cody Schuffelen TPM_HANDLE *handle // OUT: the handle of the next item.
400*5c591343SA. Cody Schuffelen )
401*5c591343SA. Cody Schuffelen {
402*5c591343SA. Cody Schuffelen NV_RAM_REF currentAddr;
403*5c591343SA. Cody Schuffelen NV_RAM_HEADER header;
404*5c591343SA. Cody Schuffelen //
405*5c591343SA. Cody Schuffelen // If iterator is at the beginning of list
406*5c591343SA. Cody Schuffelen if(*iter == NV_RAM_REF_INIT)
407*5c591343SA. Cody Schuffelen {
408*5c591343SA. Cody Schuffelen // Initialize iterator
409*5c591343SA. Cody Schuffelen *iter = &s_indexOrderlyRam[0];
410*5c591343SA. Cody Schuffelen }
411*5c591343SA. Cody Schuffelen // if we are going to return what the iter is currently pointing to...
412*5c591343SA. Cody Schuffelen currentAddr = *iter;
413*5c591343SA. Cody Schuffelen
414*5c591343SA. Cody Schuffelen // If iterator reaches the end of NV space, then don't advance and return
415*5c591343SA. Cody Schuffelen // that we are at the end of the list. The end of the list occurs when
416*5c591343SA. Cody Schuffelen // we don't have space for a size and a handle
417*5c591343SA. Cody Schuffelen if(currentAddr + sizeof(NV_RAM_HEADER) > RAM_ORDERLY_END)
418*5c591343SA. Cody Schuffelen return NULL;
419*5c591343SA. Cody Schuffelen // read the header of the next entry
420*5c591343SA. Cody Schuffelen MemoryCopy(&header, currentAddr, sizeof(NV_RAM_HEADER));
421*5c591343SA. Cody Schuffelen
422*5c591343SA. Cody Schuffelen // if the size field is zero, then we have hit the end of the list
423*5c591343SA. Cody Schuffelen if(header.size == 0)
424*5c591343SA. Cody Schuffelen // leave the *iter pointing at the end of the list
425*5c591343SA. Cody Schuffelen return NULL;
426*5c591343SA. Cody Schuffelen // advance the header by the size of the entry
427*5c591343SA. Cody Schuffelen *iter = currentAddr + header.size;
428*5c591343SA. Cody Schuffelen
429*5c591343SA. Cody Schuffelen // pAssert(*iter <= RAM_ORDERLY_END);
430*5c591343SA. Cody Schuffelen if(handle != NULL)
431*5c591343SA. Cody Schuffelen *handle = header.handle;
432*5c591343SA. Cody Schuffelen return currentAddr;
433*5c591343SA. Cody Schuffelen }
434*5c591343SA. Cody Schuffelen
435*5c591343SA. Cody Schuffelen //*** NvRamGetEnd()
436*5c591343SA. Cody Schuffelen // This routine performs the same function as NvGetEnd() but for the RAM data.
437*5c591343SA. Cody Schuffelen static NV_RAM_REF
NvRamGetEnd(void)438*5c591343SA. Cody Schuffelen NvRamGetEnd(
439*5c591343SA. Cody Schuffelen void
440*5c591343SA. Cody Schuffelen )
441*5c591343SA. Cody Schuffelen {
442*5c591343SA. Cody Schuffelen NV_RAM_REF iter = NV_RAM_REF_INIT;
443*5c591343SA. Cody Schuffelen NV_RAM_REF currentAddr;
444*5c591343SA. Cody Schuffelen //
445*5c591343SA. Cody Schuffelen // Scan until the next address is 0
446*5c591343SA. Cody Schuffelen while((currentAddr = NvRamNext(&iter, NULL)) != 0);
447*5c591343SA. Cody Schuffelen return iter;
448*5c591343SA. Cody Schuffelen }
449*5c591343SA. Cody Schuffelen
450*5c591343SA. Cody Schuffelen //*** NvRamTestSpaceIndex()
451*5c591343SA. Cody Schuffelen // This function indicates if there is enough RAM space to add a data for a
452*5c591343SA. Cody Schuffelen // new NV Index.
453*5c591343SA. Cody Schuffelen // Return Type: BOOL
454*5c591343SA. Cody Schuffelen // TRUE(1) space available
455*5c591343SA. Cody Schuffelen // FALSE(0) no enough space
456*5c591343SA. Cody Schuffelen static BOOL
NvRamTestSpaceIndex(UINT32 size)457*5c591343SA. Cody Schuffelen NvRamTestSpaceIndex(
458*5c591343SA. Cody Schuffelen UINT32 size // IN: size of the data to be added to RAM
459*5c591343SA. Cody Schuffelen )
460*5c591343SA. Cody Schuffelen {
461*5c591343SA. Cody Schuffelen UINT32 remaining = (UINT32)(RAM_ORDERLY_END - NvRamGetEnd());
462*5c591343SA. Cody Schuffelen UINT32 needed = sizeof(NV_RAM_HEADER) + size;
463*5c591343SA. Cody Schuffelen //
464*5c591343SA. Cody Schuffelen // NvRamGetEnd points to the next available byte.
465*5c591343SA. Cody Schuffelen return remaining >= needed;
466*5c591343SA. Cody Schuffelen }
467*5c591343SA. Cody Schuffelen
468*5c591343SA. Cody Schuffelen //*** NvRamGetIndex()
469*5c591343SA. Cody Schuffelen // This function returns the offset of NV data in the RAM buffer
470*5c591343SA. Cody Schuffelen //
471*5c591343SA. Cody Schuffelen // This function requires that NV Index is in RAM. That is, the
472*5c591343SA. Cody Schuffelen // index must be known to exist.
473*5c591343SA. Cody Schuffelen static NV_RAM_REF
NvRamGetIndex(TPMI_RH_NV_INDEX handle)474*5c591343SA. Cody Schuffelen NvRamGetIndex(
475*5c591343SA. Cody Schuffelen TPMI_RH_NV_INDEX handle // IN: NV handle
476*5c591343SA. Cody Schuffelen )
477*5c591343SA. Cody Schuffelen {
478*5c591343SA. Cody Schuffelen NV_RAM_REF iter = NV_RAM_REF_INIT;
479*5c591343SA. Cody Schuffelen NV_RAM_REF currentAddr;
480*5c591343SA. Cody Schuffelen TPM_HANDLE foundHandle;
481*5c591343SA. Cody Schuffelen //
482*5c591343SA. Cody Schuffelen while((currentAddr = NvRamNext(&iter, &foundHandle)) != 0)
483*5c591343SA. Cody Schuffelen {
484*5c591343SA. Cody Schuffelen if(handle == foundHandle)
485*5c591343SA. Cody Schuffelen break;
486*5c591343SA. Cody Schuffelen }
487*5c591343SA. Cody Schuffelen return currentAddr;
488*5c591343SA. Cody Schuffelen }
489*5c591343SA. Cody Schuffelen
490*5c591343SA. Cody Schuffelen //*** NvUpdateIndexOrderlyData()
491*5c591343SA. Cody Schuffelen // This function is used to cause an update of the orderly data to the NV backing
492*5c591343SA. Cody Schuffelen // store.
493*5c591343SA. Cody Schuffelen void
NvUpdateIndexOrderlyData(void)494*5c591343SA. Cody Schuffelen NvUpdateIndexOrderlyData(
495*5c591343SA. Cody Schuffelen void
496*5c591343SA. Cody Schuffelen )
497*5c591343SA. Cody Schuffelen {
498*5c591343SA. Cody Schuffelen // Write reserved RAM space to NV
499*5c591343SA. Cody Schuffelen NvWrite(NV_INDEX_RAM_DATA, sizeof(s_indexOrderlyRam), s_indexOrderlyRam);
500*5c591343SA. Cody Schuffelen }
501*5c591343SA. Cody Schuffelen
502*5c591343SA. Cody Schuffelen //*** NvAddRAM()
503*5c591343SA. Cody Schuffelen // This function adds a new data area to RAM.
504*5c591343SA. Cody Schuffelen //
505*5c591343SA. Cody Schuffelen // This function requires that enough free RAM space is available to add
506*5c591343SA. Cody Schuffelen // the new data.
507*5c591343SA. Cody Schuffelen //
508*5c591343SA. Cody Schuffelen // This function should be called after the NV Index space has been updated
509*5c591343SA. Cody Schuffelen // and the index removed. This insures that NV is available so that checking
510*5c591343SA. Cody Schuffelen // for NV availability is not required during this function.
511*5c591343SA. Cody Schuffelen static void
NvAddRAM(TPMS_NV_PUBLIC * index)512*5c591343SA. Cody Schuffelen NvAddRAM(
513*5c591343SA. Cody Schuffelen TPMS_NV_PUBLIC *index // IN: the index descriptor
514*5c591343SA. Cody Schuffelen )
515*5c591343SA. Cody Schuffelen {
516*5c591343SA. Cody Schuffelen NV_RAM_HEADER header;
517*5c591343SA. Cody Schuffelen NV_RAM_REF end = NvRamGetEnd();
518*5c591343SA. Cody Schuffelen //
519*5c591343SA. Cody Schuffelen header.size = sizeof(NV_RAM_HEADER) + index->dataSize;
520*5c591343SA. Cody Schuffelen header.handle = index->nvIndex;
521*5c591343SA. Cody Schuffelen MemoryCopy(&header.attributes, &index->attributes, sizeof(TPMA_NV));
522*5c591343SA. Cody Schuffelen
523*5c591343SA. Cody Schuffelen pAssert(ORDERLY_RAM_ADDRESS_OK(end, header.size));
524*5c591343SA. Cody Schuffelen
525*5c591343SA. Cody Schuffelen // Copy the header to the memory
526*5c591343SA. Cody Schuffelen MemoryCopy(end, &header, sizeof(NV_RAM_HEADER));
527*5c591343SA. Cody Schuffelen
528*5c591343SA. Cody Schuffelen // Clear the data area (just in case)
529*5c591343SA. Cody Schuffelen MemorySet(end + sizeof(NV_RAM_HEADER), 0, index->dataSize);
530*5c591343SA. Cody Schuffelen
531*5c591343SA. Cody Schuffelen // Step over this new entry
532*5c591343SA. Cody Schuffelen end += header.size;
533*5c591343SA. Cody Schuffelen
534*5c591343SA. Cody Schuffelen // If the end marker will fit, add it
535*5c591343SA. Cody Schuffelen if(end + sizeof(UINT32) < RAM_ORDERLY_END)
536*5c591343SA. Cody Schuffelen MemorySet(end, 0, sizeof(UINT32));
537*5c591343SA. Cody Schuffelen // Write reserved RAM space to NV to reflect the newly added NV Index
538*5c591343SA. Cody Schuffelen SET_NV_UPDATE(UT_ORDERLY);
539*5c591343SA. Cody Schuffelen
540*5c591343SA. Cody Schuffelen return;
541*5c591343SA. Cody Schuffelen }
542*5c591343SA. Cody Schuffelen
543*5c591343SA. Cody Schuffelen //*** NvDeleteRAM()
544*5c591343SA. Cody Schuffelen // This function is used to delete a RAM-backed NV Index data area.
545*5c591343SA. Cody Schuffelen // The space used by the entry are overwritten by the contents of the
546*5c591343SA. Cody Schuffelen // Index data that comes after (the data is moved up to fill the hole left
547*5c591343SA. Cody Schuffelen // by removing this index. The reclaimed space is cleared to zeros.
548*5c591343SA. Cody Schuffelen // This function assumes the data of NV Index exists in RAM.
549*5c591343SA. Cody Schuffelen //
550*5c591343SA. Cody Schuffelen // This function should be called after the NV Index space has been updated
551*5c591343SA. Cody Schuffelen // and the index removed. This insures that NV is available so that checking
552*5c591343SA. Cody Schuffelen // for NV availability is not required during this function.
553*5c591343SA. Cody Schuffelen static void
NvDeleteRAM(TPMI_RH_NV_INDEX handle)554*5c591343SA. Cody Schuffelen NvDeleteRAM(
555*5c591343SA. Cody Schuffelen TPMI_RH_NV_INDEX handle // IN: NV handle
556*5c591343SA. Cody Schuffelen )
557*5c591343SA. Cody Schuffelen {
558*5c591343SA. Cody Schuffelen NV_RAM_REF nodeAddress;
559*5c591343SA. Cody Schuffelen NV_RAM_REF nextNode;
560*5c591343SA. Cody Schuffelen UINT32 size;
561*5c591343SA. Cody Schuffelen NV_RAM_REF lastUsed = NvRamGetEnd();
562*5c591343SA. Cody Schuffelen //
563*5c591343SA. Cody Schuffelen nodeAddress = NvRamGetIndex(handle);
564*5c591343SA. Cody Schuffelen
565*5c591343SA. Cody Schuffelen pAssert(nodeAddress != 0);
566*5c591343SA. Cody Schuffelen
567*5c591343SA. Cody Schuffelen // Get node size
568*5c591343SA. Cody Schuffelen MemoryCopy(&size, nodeAddress, sizeof(size));
569*5c591343SA. Cody Schuffelen
570*5c591343SA. Cody Schuffelen // Get the offset of next node
571*5c591343SA. Cody Schuffelen nextNode = nodeAddress + size;
572*5c591343SA. Cody Schuffelen
573*5c591343SA. Cody Schuffelen // Copy the data
574*5c591343SA. Cody Schuffelen MemoryCopy(nodeAddress, nextNode, (int)(lastUsed - nextNode));
575*5c591343SA. Cody Schuffelen
576*5c591343SA. Cody Schuffelen // Clear out the reclaimed space
577*5c591343SA. Cody Schuffelen MemorySet(lastUsed - size, 0, size);
578*5c591343SA. Cody Schuffelen
579*5c591343SA. Cody Schuffelen // Write reserved RAM space to NV to reflect the newly delete NV Index
580*5c591343SA. Cody Schuffelen SET_NV_UPDATE(UT_ORDERLY);
581*5c591343SA. Cody Schuffelen
582*5c591343SA. Cody Schuffelen return;
583*5c591343SA. Cody Schuffelen }
584*5c591343SA. Cody Schuffelen
585*5c591343SA. Cody Schuffelen //*** NvReadIndex()
586*5c591343SA. Cody Schuffelen // This function is used to read the NV Index NV_INDEX. This is used so that the
587*5c591343SA. Cody Schuffelen // index information can be compressed and only this function would be needed
588*5c591343SA. Cody Schuffelen // to decompress it. Mostly, compression would only be able to save the space
589*5c591343SA. Cody Schuffelen // needed by the policy.
590*5c591343SA. Cody Schuffelen void
NvReadNvIndexInfo(NV_REF ref,NV_INDEX * nvIndex)591*5c591343SA. Cody Schuffelen NvReadNvIndexInfo(
592*5c591343SA. Cody Schuffelen NV_REF ref, // IN: points to NV where index is located
593*5c591343SA. Cody Schuffelen NV_INDEX *nvIndex // OUT: place to receive index data
594*5c591343SA. Cody Schuffelen )
595*5c591343SA. Cody Schuffelen {
596*5c591343SA. Cody Schuffelen pAssert(nvIndex != NULL);
597*5c591343SA. Cody Schuffelen NvRead(nvIndex, ref, sizeof(NV_INDEX));
598*5c591343SA. Cody Schuffelen return;
599*5c591343SA. Cody Schuffelen }
600*5c591343SA. Cody Schuffelen
601*5c591343SA. Cody Schuffelen //*** NvReadObject()
602*5c591343SA. Cody Schuffelen // This function is used to read a persistent object. This is used so that the
603*5c591343SA. Cody Schuffelen // object information can be compressed and only this function would be needed
604*5c591343SA. Cody Schuffelen // to uncompress it.
605*5c591343SA. Cody Schuffelen void
NvReadObject(NV_REF ref,OBJECT * object)606*5c591343SA. Cody Schuffelen NvReadObject(
607*5c591343SA. Cody Schuffelen NV_REF ref, // IN: points to NV where index is located
608*5c591343SA. Cody Schuffelen OBJECT *object // OUT: place to receive the object data
609*5c591343SA. Cody Schuffelen )
610*5c591343SA. Cody Schuffelen {
611*5c591343SA. Cody Schuffelen NvRead(object, (ref + sizeof(TPM_HANDLE)), sizeof(OBJECT));
612*5c591343SA. Cody Schuffelen return;
613*5c591343SA. Cody Schuffelen }
614*5c591343SA. Cody Schuffelen
615*5c591343SA. Cody Schuffelen //*** NvFindEvict()
616*5c591343SA. Cody Schuffelen // This function will return the NV offset of an evict object
617*5c591343SA. Cody Schuffelen // Return Type: UINT32
618*5c591343SA. Cody Schuffelen // 0 evict object not found
619*5c591343SA. Cody Schuffelen // != 0 offset of evict object
620*5c591343SA. Cody Schuffelen static NV_REF
NvFindEvict(TPM_HANDLE nvHandle,OBJECT * object)621*5c591343SA. Cody Schuffelen NvFindEvict(
622*5c591343SA. Cody Schuffelen TPM_HANDLE nvHandle,
623*5c591343SA. Cody Schuffelen OBJECT *object
624*5c591343SA. Cody Schuffelen )
625*5c591343SA. Cody Schuffelen {
626*5c591343SA. Cody Schuffelen NV_REF found = NvFindHandle(nvHandle);
627*5c591343SA. Cody Schuffelen //
628*5c591343SA. Cody Schuffelen // If we found the handle and the request included an object pointer, fill it in
629*5c591343SA. Cody Schuffelen if(found != 0 && object != NULL)
630*5c591343SA. Cody Schuffelen NvReadObject(found, object);
631*5c591343SA. Cody Schuffelen return found;
632*5c591343SA. Cody Schuffelen }
633*5c591343SA. Cody Schuffelen
634*5c591343SA. Cody Schuffelen //*** NvIndexIsDefined()
635*5c591343SA. Cody Schuffelen // See if an index is already defined
636*5c591343SA. Cody Schuffelen BOOL
NvIndexIsDefined(TPM_HANDLE nvHandle)637*5c591343SA. Cody Schuffelen NvIndexIsDefined(
638*5c591343SA. Cody Schuffelen TPM_HANDLE nvHandle // IN: Index to look for
639*5c591343SA. Cody Schuffelen )
640*5c591343SA. Cody Schuffelen {
641*5c591343SA. Cody Schuffelen return (NvFindHandle(nvHandle) != 0);
642*5c591343SA. Cody Schuffelen }
643*5c591343SA. Cody Schuffelen
644*5c591343SA. Cody Schuffelen //*** NvConditionallyWrite()
645*5c591343SA. Cody Schuffelen // Function to check if the data to be written has changed
646*5c591343SA. Cody Schuffelen // and write it if it has
647*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
648*5c591343SA. Cody Schuffelen // TPM_RC_NV_RATE NV is unavailable because of rate limit
649*5c591343SA. Cody Schuffelen // TPM_RC_NV_UNAVAILABLE NV is inaccessible
650*5c591343SA. Cody Schuffelen static TPM_RC
NvConditionallyWrite(NV_REF entryAddr,UINT32 size,void * data)651*5c591343SA. Cody Schuffelen NvConditionallyWrite(
652*5c591343SA. Cody Schuffelen NV_REF entryAddr, // IN: stating address
653*5c591343SA. Cody Schuffelen UINT32 size, // IN: size of the data to write
654*5c591343SA. Cody Schuffelen void *data // IN: the data to write
655*5c591343SA. Cody Schuffelen )
656*5c591343SA. Cody Schuffelen {
657*5c591343SA. Cody Schuffelen // If the index data is actually changed, then a write to NV is required
658*5c591343SA. Cody Schuffelen if(_plat__NvIsDifferent(entryAddr, size, data))
659*5c591343SA. Cody Schuffelen {
660*5c591343SA. Cody Schuffelen // Write the data if NV is available
661*5c591343SA. Cody Schuffelen if(g_NvStatus == TPM_RC_SUCCESS)
662*5c591343SA. Cody Schuffelen {
663*5c591343SA. Cody Schuffelen NvWrite(entryAddr, size, data);
664*5c591343SA. Cody Schuffelen }
665*5c591343SA. Cody Schuffelen return g_NvStatus;
666*5c591343SA. Cody Schuffelen }
667*5c591343SA. Cody Schuffelen return TPM_RC_SUCCESS;
668*5c591343SA. Cody Schuffelen }
669*5c591343SA. Cody Schuffelen
670*5c591343SA. Cody Schuffelen //*** NvReadNvIndexAttributes()
671*5c591343SA. Cody Schuffelen // This function returns the attributes of an NV Index.
672*5c591343SA. Cody Schuffelen static TPMA_NV
NvReadNvIndexAttributes(NV_REF locator)673*5c591343SA. Cody Schuffelen NvReadNvIndexAttributes(
674*5c591343SA. Cody Schuffelen NV_REF locator // IN: reference to an NV index
675*5c591343SA. Cody Schuffelen )
676*5c591343SA. Cody Schuffelen {
677*5c591343SA. Cody Schuffelen TPMA_NV attributes;
678*5c591343SA. Cody Schuffelen //
679*5c591343SA. Cody Schuffelen NvRead(&attributes,
680*5c591343SA. Cody Schuffelen locator + offsetof(NV_INDEX, publicArea.attributes),
681*5c591343SA. Cody Schuffelen sizeof(TPMA_NV));
682*5c591343SA. Cody Schuffelen return attributes;
683*5c591343SA. Cody Schuffelen }
684*5c591343SA. Cody Schuffelen
685*5c591343SA. Cody Schuffelen //*** NvReadRamIndexAttributes()
686*5c591343SA. Cody Schuffelen // This function returns the attributes from the RAM header structure. This function
687*5c591343SA. Cody Schuffelen // is used to deal with the fact that the header structure is only byte aligned.
688*5c591343SA. Cody Schuffelen static TPMA_NV
NvReadRamIndexAttributes(NV_RAM_REF ref)689*5c591343SA. Cody Schuffelen NvReadRamIndexAttributes(
690*5c591343SA. Cody Schuffelen NV_RAM_REF ref // IN: pointer to a NV_RAM_HEADER
691*5c591343SA. Cody Schuffelen )
692*5c591343SA. Cody Schuffelen {
693*5c591343SA. Cody Schuffelen TPMA_NV attributes;
694*5c591343SA. Cody Schuffelen //
695*5c591343SA. Cody Schuffelen MemoryCopy(&attributes, ref + offsetof(NV_RAM_HEADER, attributes),
696*5c591343SA. Cody Schuffelen sizeof(TPMA_NV));
697*5c591343SA. Cody Schuffelen return attributes;
698*5c591343SA. Cody Schuffelen }
699*5c591343SA. Cody Schuffelen
700*5c591343SA. Cody Schuffelen //*** NvWriteNvIndexAttributes()
701*5c591343SA. Cody Schuffelen // This function is used to write just the attributes of an index to NV.
702*5c591343SA. Cody Schuffelen // Return type: TPM_RC
703*5c591343SA. Cody Schuffelen // TPM_RC_NV_RATE NV is rate limiting so retry
704*5c591343SA. Cody Schuffelen // TPM_RC_NV_UNAVAILABLE NV is not available
705*5c591343SA. Cody Schuffelen static TPM_RC
NvWriteNvIndexAttributes(NV_REF locator,TPMA_NV attributes)706*5c591343SA. Cody Schuffelen NvWriteNvIndexAttributes(
707*5c591343SA. Cody Schuffelen NV_REF locator, // IN: location of the index
708*5c591343SA. Cody Schuffelen TPMA_NV attributes // IN: attributes to write
709*5c591343SA. Cody Schuffelen )
710*5c591343SA. Cody Schuffelen {
711*5c591343SA. Cody Schuffelen return NvConditionallyWrite(
712*5c591343SA. Cody Schuffelen locator + offsetof(NV_INDEX, publicArea.attributes),
713*5c591343SA. Cody Schuffelen sizeof(TPMA_NV),
714*5c591343SA. Cody Schuffelen &attributes);
715*5c591343SA. Cody Schuffelen }
716*5c591343SA. Cody Schuffelen
717*5c591343SA. Cody Schuffelen //*** NvWriteRamIndexAttributes()
718*5c591343SA. Cody Schuffelen // This function is used to write the index attributes into an unaligned structure
719*5c591343SA. Cody Schuffelen static void
NvWriteRamIndexAttributes(NV_RAM_REF ref,TPMA_NV attributes)720*5c591343SA. Cody Schuffelen NvWriteRamIndexAttributes(
721*5c591343SA. Cody Schuffelen NV_RAM_REF ref, // IN: address of the header
722*5c591343SA. Cody Schuffelen TPMA_NV attributes // IN: the attributes to write
723*5c591343SA. Cody Schuffelen )
724*5c591343SA. Cody Schuffelen {
725*5c591343SA. Cody Schuffelen MemoryCopy(ref + offsetof(NV_RAM_HEADER, attributes), &attributes,
726*5c591343SA. Cody Schuffelen sizeof(TPMA_NV));
727*5c591343SA. Cody Schuffelen return;
728*5c591343SA. Cody Schuffelen }
729*5c591343SA. Cody Schuffelen
730*5c591343SA. Cody Schuffelen //************************************************
731*5c591343SA. Cody Schuffelen //** Externally Accessible Functions
732*5c591343SA. Cody Schuffelen //************************************************
733*5c591343SA. Cody Schuffelen
734*5c591343SA. Cody Schuffelen //*** NvIsPlatformPersistentHandle()
735*5c591343SA. Cody Schuffelen // This function indicates if a handle references a persistent object in the
736*5c591343SA. Cody Schuffelen // range belonging to the platform.
737*5c591343SA. Cody Schuffelen // Return Type: BOOL
738*5c591343SA. Cody Schuffelen // TRUE(1) handle references a platform persistent object
739*5c591343SA. Cody Schuffelen // FALSE(0) handle does not reference platform persistent object
740*5c591343SA. Cody Schuffelen BOOL
NvIsPlatformPersistentHandle(TPM_HANDLE handle)741*5c591343SA. Cody Schuffelen NvIsPlatformPersistentHandle(
742*5c591343SA. Cody Schuffelen TPM_HANDLE handle // IN: handle
743*5c591343SA. Cody Schuffelen )
744*5c591343SA. Cody Schuffelen {
745*5c591343SA. Cody Schuffelen return (handle >= PLATFORM_PERSISTENT && handle <= PERSISTENT_LAST);
746*5c591343SA. Cody Schuffelen }
747*5c591343SA. Cody Schuffelen
748*5c591343SA. Cody Schuffelen //*** NvIsOwnerPersistentHandle()
749*5c591343SA. Cody Schuffelen // This function indicates if a handle references a persistent object in the
750*5c591343SA. Cody Schuffelen // range belonging to the owner.
751*5c591343SA. Cody Schuffelen // Return Type: BOOL
752*5c591343SA. Cody Schuffelen // TRUE(1) handle is owner persistent handle
753*5c591343SA. Cody Schuffelen // FALSE(0) handle is not owner persistent handle and may not be
754*5c591343SA. Cody Schuffelen // a persistent handle at all
755*5c591343SA. Cody Schuffelen BOOL
NvIsOwnerPersistentHandle(TPM_HANDLE handle)756*5c591343SA. Cody Schuffelen NvIsOwnerPersistentHandle(
757*5c591343SA. Cody Schuffelen TPM_HANDLE handle // IN: handle
758*5c591343SA. Cody Schuffelen )
759*5c591343SA. Cody Schuffelen {
760*5c591343SA. Cody Schuffelen return (handle >= PERSISTENT_FIRST && handle < PLATFORM_PERSISTENT);
761*5c591343SA. Cody Schuffelen }
762*5c591343SA. Cody Schuffelen
763*5c591343SA. Cody Schuffelen //*** NvIndexIsAccessible()
764*5c591343SA. Cody Schuffelen //
765*5c591343SA. Cody Schuffelen // This function validates that a handle references a defined NV Index and
766*5c591343SA. Cody Schuffelen // that the Index is currently accessible.
767*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
768*5c591343SA. Cody Schuffelen // TPM_RC_HANDLE the handle points to an undefined NV Index
769*5c591343SA. Cody Schuffelen // If shEnable is CLEAR, this would include an index
770*5c591343SA. Cody Schuffelen // created using ownerAuth. If phEnableNV is CLEAR,
771*5c591343SA. Cody Schuffelen // this would include and index created using
772*5c591343SA. Cody Schuffelen // platformAuth
773*5c591343SA. Cody Schuffelen // TPM_RC_NV_READLOCKED Index is present but locked for reading and command
774*5c591343SA. Cody Schuffelen // does not write to the index
775*5c591343SA. Cody Schuffelen // TPM_RC_NV_WRITELOCKED Index is present but locked for writing and command
776*5c591343SA. Cody Schuffelen // writes to the index
777*5c591343SA. Cody Schuffelen TPM_RC
NvIndexIsAccessible(TPMI_RH_NV_INDEX handle)778*5c591343SA. Cody Schuffelen NvIndexIsAccessible(
779*5c591343SA. Cody Schuffelen TPMI_RH_NV_INDEX handle // IN: handle
780*5c591343SA. Cody Schuffelen )
781*5c591343SA. Cody Schuffelen {
782*5c591343SA. Cody Schuffelen NV_INDEX *nvIndex = NvGetIndexInfo(handle, NULL);
783*5c591343SA. Cody Schuffelen //
784*5c591343SA. Cody Schuffelen if(nvIndex == NULL)
785*5c591343SA. Cody Schuffelen // If index is not found, return TPM_RC_HANDLE
786*5c591343SA. Cody Schuffelen return TPM_RC_HANDLE;
787*5c591343SA. Cody Schuffelen if(gc.shEnable == FALSE || gc.phEnableNV == FALSE)
788*5c591343SA. Cody Schuffelen {
789*5c591343SA. Cody Schuffelen // if shEnable is CLEAR, an ownerCreate NV Index should not be
790*5c591343SA. Cody Schuffelen // indicated as present
791*5c591343SA. Cody Schuffelen if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, PLATFORMCREATE))
792*5c591343SA. Cody Schuffelen {
793*5c591343SA. Cody Schuffelen if(gc.shEnable == FALSE)
794*5c591343SA. Cody Schuffelen return TPM_RC_HANDLE;
795*5c591343SA. Cody Schuffelen }
796*5c591343SA. Cody Schuffelen // if phEnableNV is CLEAR, a platform created Index should not
797*5c591343SA. Cody Schuffelen // be visible
798*5c591343SA. Cody Schuffelen else if(gc.phEnableNV == FALSE)
799*5c591343SA. Cody Schuffelen return TPM_RC_HANDLE;
800*5c591343SA. Cody Schuffelen }
801*5c591343SA. Cody Schuffelen #if 0 // Writelock test for debug
802*5c591343SA. Cody Schuffelen // If the Index is write locked and this is an NV Write operation...
803*5c591343SA. Cody Schuffelen if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITELOCKED)
804*5c591343SA. Cody Schuffelen && IsWriteOperation(commandIndex))
805*5c591343SA. Cody Schuffelen {
806*5c591343SA. Cody Schuffelen // then return a locked indication unless the command is TPM2_NV_WriteLock
807*5c591343SA. Cody Schuffelen if(GetCommandCode(commandIndex) != TPM_CC_NV_WriteLock)
808*5c591343SA. Cody Schuffelen return TPM_RC_NV_LOCKED;
809*5c591343SA. Cody Schuffelen return TPM_RC_SUCCESS;
810*5c591343SA. Cody Schuffelen }
811*5c591343SA. Cody Schuffelen #endif
812*5c591343SA. Cody Schuffelen #if 0 // Readlock Test for debug
813*5c591343SA. Cody Schuffelen // If the Index is read locked and this is an NV Read operation...
814*5c591343SA. Cody Schuffelen if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, READLOCKED)
815*5c591343SA. Cody Schuffelen && IsReadOperation(commandIndex))
816*5c591343SA. Cody Schuffelen {
817*5c591343SA. Cody Schuffelen // then return a locked indication unless the command is TPM2_NV_ReadLock
818*5c591343SA. Cody Schuffelen if(GetCommandCode(commandIndex) != TPM_CC_NV_ReadLock)
819*5c591343SA. Cody Schuffelen return TPM_RC_NV_LOCKED;
820*5c591343SA. Cody Schuffelen }
821*5c591343SA. Cody Schuffelen #endif
822*5c591343SA. Cody Schuffelen // NV Index is accessible
823*5c591343SA. Cody Schuffelen return TPM_RC_SUCCESS;
824*5c591343SA. Cody Schuffelen }
825*5c591343SA. Cody Schuffelen
826*5c591343SA. Cody Schuffelen //*** NvGetEvictObject()
827*5c591343SA. Cody Schuffelen // This function is used to dereference an evict object handle and get a pointer
828*5c591343SA. Cody Schuffelen // to the object.
829*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
830*5c591343SA. Cody Schuffelen // TPM_RC_HANDLE the handle does not point to an existing
831*5c591343SA. Cody Schuffelen // persistent object
832*5c591343SA. Cody Schuffelen TPM_RC
NvGetEvictObject(TPM_HANDLE handle,OBJECT * object)833*5c591343SA. Cody Schuffelen NvGetEvictObject(
834*5c591343SA. Cody Schuffelen TPM_HANDLE handle, // IN: handle
835*5c591343SA. Cody Schuffelen OBJECT *object // OUT: object data
836*5c591343SA. Cody Schuffelen )
837*5c591343SA. Cody Schuffelen {
838*5c591343SA. Cody Schuffelen NV_REF entityAddr; // offset points to the entity
839*5c591343SA. Cody Schuffelen //
840*5c591343SA. Cody Schuffelen // Find the address of evict object and copy to object
841*5c591343SA. Cody Schuffelen entityAddr = NvFindEvict(handle, object);
842*5c591343SA. Cody Schuffelen
843*5c591343SA. Cody Schuffelen // whether there is an error or not, make sure that the evict
844*5c591343SA. Cody Schuffelen // status of the object is set so that the slot will get freed on exit
845*5c591343SA. Cody Schuffelen // Must do this after NvFindEvict loads the object
846*5c591343SA. Cody Schuffelen object->attributes.evict = SET;
847*5c591343SA. Cody Schuffelen
848*5c591343SA. Cody Schuffelen // If handle is not found, return an error
849*5c591343SA. Cody Schuffelen if(entityAddr == 0)
850*5c591343SA. Cody Schuffelen return TPM_RC_HANDLE;
851*5c591343SA. Cody Schuffelen return TPM_RC_SUCCESS;
852*5c591343SA. Cody Schuffelen }
853*5c591343SA. Cody Schuffelen
854*5c591343SA. Cody Schuffelen //*** NvIndexCacheInit()
855*5c591343SA. Cody Schuffelen // Function to initialize the Index cache
856*5c591343SA. Cody Schuffelen void
NvIndexCacheInit(void)857*5c591343SA. Cody Schuffelen NvIndexCacheInit(
858*5c591343SA. Cody Schuffelen void
859*5c591343SA. Cody Schuffelen )
860*5c591343SA. Cody Schuffelen {
861*5c591343SA. Cody Schuffelen s_cachedNvRef = NV_REF_INIT;
862*5c591343SA. Cody Schuffelen s_cachedNvRamRef = NV_RAM_REF_INIT;
863*5c591343SA. Cody Schuffelen s_cachedNvIndex.publicArea.nvIndex = TPM_RH_UNASSIGNED;
864*5c591343SA. Cody Schuffelen return;
865*5c591343SA. Cody Schuffelen }
866*5c591343SA. Cody Schuffelen
867*5c591343SA. Cody Schuffelen
868*5c591343SA. Cody Schuffelen //*** NvGetIndexData()
869*5c591343SA. Cody Schuffelen // This function is used to access the data in an NV Index. The data is returned
870*5c591343SA. Cody Schuffelen // as a byte sequence.
871*5c591343SA. Cody Schuffelen //
872*5c591343SA. Cody Schuffelen // This function requires that the NV Index be defined, and that the
873*5c591343SA. Cody Schuffelen // required data is within the data range. It also requires that TPMA_NV_WRITTEN
874*5c591343SA. Cody Schuffelen // of the Index is SET.
875*5c591343SA. Cody Schuffelen void
NvGetIndexData(NV_INDEX * nvIndex,NV_REF locator,UINT32 offset,UINT16 size,void * data)876*5c591343SA. Cody Schuffelen NvGetIndexData(
877*5c591343SA. Cody Schuffelen NV_INDEX *nvIndex, // IN: the in RAM index descriptor
878*5c591343SA. Cody Schuffelen NV_REF locator, // IN: where the data is located
879*5c591343SA. Cody Schuffelen UINT32 offset, // IN: offset of NV data
880*5c591343SA. Cody Schuffelen UINT16 size, // IN: number of octets of NV data to read
881*5c591343SA. Cody Schuffelen void *data // OUT: data buffer
882*5c591343SA. Cody Schuffelen )
883*5c591343SA. Cody Schuffelen {
884*5c591343SA. Cody Schuffelen TPMA_NV nvAttributes;
885*5c591343SA. Cody Schuffelen //
886*5c591343SA. Cody Schuffelen pAssert(nvIndex != NULL);
887*5c591343SA. Cody Schuffelen
888*5c591343SA. Cody Schuffelen nvAttributes = nvIndex->publicArea.attributes;
889*5c591343SA. Cody Schuffelen
890*5c591343SA. Cody Schuffelen pAssert(IS_ATTRIBUTE(nvAttributes, TPMA_NV, WRITTEN));
891*5c591343SA. Cody Schuffelen
892*5c591343SA. Cody Schuffelen if(IS_ATTRIBUTE(nvAttributes, TPMA_NV, ORDERLY))
893*5c591343SA. Cody Schuffelen {
894*5c591343SA. Cody Schuffelen // Get data from RAM buffer
895*5c591343SA. Cody Schuffelen NV_RAM_REF ramAddr = NvRamGetIndex(nvIndex->publicArea.nvIndex);
896*5c591343SA. Cody Schuffelen pAssert(ramAddr != 0 && (size <=
897*5c591343SA. Cody Schuffelen ((NV_RAM_HEADER *)ramAddr)->size - sizeof(NV_RAM_HEADER) - offset));
898*5c591343SA. Cody Schuffelen MemoryCopy(data, ramAddr + sizeof(NV_RAM_HEADER) + offset, size);
899*5c591343SA. Cody Schuffelen }
900*5c591343SA. Cody Schuffelen else
901*5c591343SA. Cody Schuffelen {
902*5c591343SA. Cody Schuffelen // Validate that read falls within range of the index
903*5c591343SA. Cody Schuffelen pAssert(offset <= nvIndex->publicArea.dataSize
904*5c591343SA. Cody Schuffelen && size <= (nvIndex->publicArea.dataSize - offset));
905*5c591343SA. Cody Schuffelen NvRead(data, locator + sizeof(NV_INDEX) + offset, size);
906*5c591343SA. Cody Schuffelen }
907*5c591343SA. Cody Schuffelen return;
908*5c591343SA. Cody Schuffelen }
909*5c591343SA. Cody Schuffelen
910*5c591343SA. Cody Schuffelen //*** NvHashIndexData()
911*5c591343SA. Cody Schuffelen // This function adds Index data to a hash. It does this in parts to avoid large stack
912*5c591343SA. Cody Schuffelen // buffers.
913*5c591343SA. Cody Schuffelen void
NvHashIndexData(HASH_STATE * hashState,NV_INDEX * nvIndex,NV_REF locator,UINT32 offset,UINT16 size)914*5c591343SA. Cody Schuffelen NvHashIndexData(
915*5c591343SA. Cody Schuffelen HASH_STATE *hashState, // IN: Initialized hash state
916*5c591343SA. Cody Schuffelen NV_INDEX *nvIndex, // IN: Index
917*5c591343SA. Cody Schuffelen NV_REF locator, // IN: where the data is located
918*5c591343SA. Cody Schuffelen UINT32 offset, // IN: starting offset
919*5c591343SA. Cody Schuffelen UINT16 size // IN: amount to hash
920*5c591343SA. Cody Schuffelen )
921*5c591343SA. Cody Schuffelen {
922*5c591343SA. Cody Schuffelen #define BUFFER_SIZE 64
923*5c591343SA. Cody Schuffelen BYTE buffer[BUFFER_SIZE];
924*5c591343SA. Cody Schuffelen if (offset > nvIndex->publicArea.dataSize)
925*5c591343SA. Cody Schuffelen return;
926*5c591343SA. Cody Schuffelen // Make sure that we don't try to read off the end.
927*5c591343SA. Cody Schuffelen if ((offset + size) > nvIndex->publicArea.dataSize)
928*5c591343SA. Cody Schuffelen size = nvIndex->publicArea.dataSize - (UINT16)offset;
929*5c591343SA. Cody Schuffelen #if BUFFER_SIZE >= MAX_NV_INDEX_SIZE
930*5c591343SA. Cody Schuffelen NvGetIndexData(nvIndex, locator, offset, size, buffer);
931*5c591343SA. Cody Schuffelen CryptDigestUpdate(hashState, size, buffer);
932*5c591343SA. Cody Schuffelen #else
933*5c591343SA. Cody Schuffelen {
934*5c591343SA. Cody Schuffelen INT16 i;
935*5c591343SA. Cody Schuffelen UINT16 readSize;
936*5c591343SA. Cody Schuffelen //
937*5c591343SA. Cody Schuffelen for (i = size; i > 0; offset += readSize, i -= readSize)
938*5c591343SA. Cody Schuffelen {
939*5c591343SA. Cody Schuffelen readSize = (i < BUFFER_SIZE) ? i : BUFFER_SIZE;
940*5c591343SA. Cody Schuffelen NvGetIndexData(nvIndex, locator, offset, readSize, buffer);
941*5c591343SA. Cody Schuffelen CryptDigestUpdate(hashState, readSize, buffer);
942*5c591343SA. Cody Schuffelen }
943*5c591343SA. Cody Schuffelen }
944*5c591343SA. Cody Schuffelen #endif // BUFFER_SIZE >= MAX_NV_INDEX_SIZE
945*5c591343SA. Cody Schuffelen #undef BUFFER_SIZE
946*5c591343SA. Cody Schuffelen }
947*5c591343SA. Cody Schuffelen
948*5c591343SA. Cody Schuffelen
949*5c591343SA. Cody Schuffelen //*** NvGetUINT64Data()
950*5c591343SA. Cody Schuffelen // Get data in integer format of a bit or counter NV Index.
951*5c591343SA. Cody Schuffelen //
952*5c591343SA. Cody Schuffelen // This function requires that the NV Index is defined and that the NV Index
953*5c591343SA. Cody Schuffelen // previously has been written.
954*5c591343SA. Cody Schuffelen UINT64
NvGetUINT64Data(NV_INDEX * nvIndex,NV_REF locator)955*5c591343SA. Cody Schuffelen NvGetUINT64Data(
956*5c591343SA. Cody Schuffelen NV_INDEX *nvIndex, // IN: the in RAM index descriptor
957*5c591343SA. Cody Schuffelen NV_REF locator // IN: where index exists in NV
958*5c591343SA. Cody Schuffelen )
959*5c591343SA. Cody Schuffelen {
960*5c591343SA. Cody Schuffelen UINT64 intVal;
961*5c591343SA. Cody Schuffelen //
962*5c591343SA. Cody Schuffelen // Read the value and convert it to internal format
963*5c591343SA. Cody Schuffelen NvGetIndexData(nvIndex, locator, 0, 8, &intVal);
964*5c591343SA. Cody Schuffelen return BYTE_ARRAY_TO_UINT64(((BYTE *)&intVal));
965*5c591343SA. Cody Schuffelen }
966*5c591343SA. Cody Schuffelen
967*5c591343SA. Cody Schuffelen //*** NvWriteIndexAttributes()
968*5c591343SA. Cody Schuffelen // This function is used to write just the attributes of an index.
969*5c591343SA. Cody Schuffelen // Return type: TPM_RC
970*5c591343SA. Cody Schuffelen // TPM_RC_NV_RATE NV is rate limiting so retry
971*5c591343SA. Cody Schuffelen // TPM_RC_NV_UNAVAILABLE NV is not available
972*5c591343SA. Cody Schuffelen TPM_RC
NvWriteIndexAttributes(TPM_HANDLE handle,NV_REF locator,TPMA_NV attributes)973*5c591343SA. Cody Schuffelen NvWriteIndexAttributes(
974*5c591343SA. Cody Schuffelen TPM_HANDLE handle,
975*5c591343SA. Cody Schuffelen NV_REF locator, // IN: location of the index
976*5c591343SA. Cody Schuffelen TPMA_NV attributes // IN: attributes to write
977*5c591343SA. Cody Schuffelen )
978*5c591343SA. Cody Schuffelen {
979*5c591343SA. Cody Schuffelen TPM_RC result;
980*5c591343SA. Cody Schuffelen //
981*5c591343SA. Cody Schuffelen if(IS_ATTRIBUTE(attributes, TPMA_NV, ORDERLY))
982*5c591343SA. Cody Schuffelen {
983*5c591343SA. Cody Schuffelen NV_RAM_REF ram = NvRamGetIndex(handle);
984*5c591343SA. Cody Schuffelen NvWriteRamIndexAttributes(ram, attributes);
985*5c591343SA. Cody Schuffelen result = TPM_RC_SUCCESS;
986*5c591343SA. Cody Schuffelen }
987*5c591343SA. Cody Schuffelen else
988*5c591343SA. Cody Schuffelen {
989*5c591343SA. Cody Schuffelen result = NvWriteNvIndexAttributes(locator, attributes);
990*5c591343SA. Cody Schuffelen }
991*5c591343SA. Cody Schuffelen return result;
992*5c591343SA. Cody Schuffelen }
993*5c591343SA. Cody Schuffelen
994*5c591343SA. Cody Schuffelen //*** NvWriteIndexAuth()
995*5c591343SA. Cody Schuffelen // This function is used to write the authValue of an index. It is used by
996*5c591343SA. Cody Schuffelen // TPM2_NV_ChangeAuth()
997*5c591343SA. Cody Schuffelen // Return type: TPM_RC
998*5c591343SA. Cody Schuffelen // TPM_RC_NV_RATE NV is rate limiting so retry
999*5c591343SA. Cody Schuffelen // TPM_RC_NV_UNAVAILABLE NV is not available
1000*5c591343SA. Cody Schuffelen TPM_RC
NvWriteIndexAuth(NV_REF locator,TPM2B_AUTH * authValue)1001*5c591343SA. Cody Schuffelen NvWriteIndexAuth(
1002*5c591343SA. Cody Schuffelen NV_REF locator, // IN: location of the index
1003*5c591343SA. Cody Schuffelen TPM2B_AUTH *authValue // IN: the authValue to write
1004*5c591343SA. Cody Schuffelen )
1005*5c591343SA. Cody Schuffelen {
1006*5c591343SA. Cody Schuffelen TPM_RC result;
1007*5c591343SA. Cody Schuffelen //
1008*5c591343SA. Cody Schuffelen // If the locator is pointing to the cached index value...
1009*5c591343SA. Cody Schuffelen if(locator == s_cachedNvRef)
1010*5c591343SA. Cody Schuffelen {
1011*5c591343SA. Cody Schuffelen // copy the authValue to the cached index so it will be there if we
1012*5c591343SA. Cody Schuffelen // look for it. This is a safety thing.
1013*5c591343SA. Cody Schuffelen MemoryCopy2B(&s_cachedNvIndex.authValue.b, &authValue->b,
1014*5c591343SA. Cody Schuffelen sizeof(s_cachedNvIndex.authValue.t.buffer));
1015*5c591343SA. Cody Schuffelen }
1016*5c591343SA. Cody Schuffelen result = NvConditionallyWrite(
1017*5c591343SA. Cody Schuffelen locator + offsetof(NV_INDEX, authValue),
1018*5c591343SA. Cody Schuffelen sizeof(UINT16) + authValue->t.size,
1019*5c591343SA. Cody Schuffelen authValue);
1020*5c591343SA. Cody Schuffelen return result;
1021*5c591343SA. Cody Schuffelen }
1022*5c591343SA. Cody Schuffelen
1023*5c591343SA. Cody Schuffelen //*** NvGetIndexInfo()
1024*5c591343SA. Cody Schuffelen // This function loads the nvIndex Info into the NV cache and returns a pointer
1025*5c591343SA. Cody Schuffelen // to the NV_INDEX. If the returned value is zero, the index was not found.
1026*5c591343SA. Cody Schuffelen // The 'locator' parameter, if not NULL, will be set to the offset in NV of the
1027*5c591343SA. Cody Schuffelen // Index (the location of the handle of the Index).
1028*5c591343SA. Cody Schuffelen //
1029*5c591343SA. Cody Schuffelen // This function will set the index cache. If the index is orderly, the attributes
1030*5c591343SA. Cody Schuffelen // from RAM are substituted for the attributes in the cached index
1031*5c591343SA. Cody Schuffelen NV_INDEX *
NvGetIndexInfo(TPM_HANDLE nvHandle,NV_REF * locator)1032*5c591343SA. Cody Schuffelen NvGetIndexInfo(
1033*5c591343SA. Cody Schuffelen TPM_HANDLE nvHandle, // IN: the index handle
1034*5c591343SA. Cody Schuffelen NV_REF *locator // OUT: location of the index
1035*5c591343SA. Cody Schuffelen )
1036*5c591343SA. Cody Schuffelen {
1037*5c591343SA. Cody Schuffelen if(s_cachedNvIndex.publicArea.nvIndex != nvHandle)
1038*5c591343SA. Cody Schuffelen {
1039*5c591343SA. Cody Schuffelen s_cachedNvIndex.publicArea.nvIndex = TPM_RH_UNASSIGNED;
1040*5c591343SA. Cody Schuffelen s_cachedNvRamRef = 0;
1041*5c591343SA. Cody Schuffelen s_cachedNvRef = NvFindHandle(nvHandle);
1042*5c591343SA. Cody Schuffelen if(s_cachedNvRef == 0)
1043*5c591343SA. Cody Schuffelen return NULL;
1044*5c591343SA. Cody Schuffelen NvReadNvIndexInfo(s_cachedNvRef, &s_cachedNvIndex);
1045*5c591343SA. Cody Schuffelen if(IS_ATTRIBUTE(s_cachedNvIndex.publicArea.attributes, TPMA_NV, ORDERLY))
1046*5c591343SA. Cody Schuffelen {
1047*5c591343SA. Cody Schuffelen s_cachedNvRamRef = NvRamGetIndex(nvHandle);
1048*5c591343SA. Cody Schuffelen s_cachedNvIndex.publicArea.attributes =
1049*5c591343SA. Cody Schuffelen NvReadRamIndexAttributes(s_cachedNvRamRef);
1050*5c591343SA. Cody Schuffelen }
1051*5c591343SA. Cody Schuffelen }
1052*5c591343SA. Cody Schuffelen if(locator != NULL)
1053*5c591343SA. Cody Schuffelen *locator = s_cachedNvRef;
1054*5c591343SA. Cody Schuffelen return &s_cachedNvIndex;
1055*5c591343SA. Cody Schuffelen }
1056*5c591343SA. Cody Schuffelen
1057*5c591343SA. Cody Schuffelen //*** NvWriteIndexData()
1058*5c591343SA. Cody Schuffelen // This function is used to write NV index data. It is intended to be used to
1059*5c591343SA. Cody Schuffelen // update the data associated with the default index.
1060*5c591343SA. Cody Schuffelen //
1061*5c591343SA. Cody Schuffelen // This function requires that the NV Index is defined, and the data is
1062*5c591343SA. Cody Schuffelen // within the defined data range for the index.
1063*5c591343SA. Cody Schuffelen //
1064*5c591343SA. Cody Schuffelen // Index data is only written due to a command that modifies the data in a single
1065*5c591343SA. Cody Schuffelen // index. There is no case where changes are made to multiple indexes data at the
1066*5c591343SA. Cody Schuffelen // same time. Multiple attributes may be change but not multiple index data. This
1067*5c591343SA. Cody Schuffelen // is important because we will normally be handling the index for which we have
1068*5c591343SA. Cody Schuffelen // the cached pointer values.
1069*5c591343SA. Cody Schuffelen // Return type: TPM_RC
1070*5c591343SA. Cody Schuffelen // TPM_RC_NV_RATE NV is rate limiting so retry
1071*5c591343SA. Cody Schuffelen // TPM_RC_NV_UNAVAILABLE NV is not available
1072*5c591343SA. Cody Schuffelen TPM_RC
NvWriteIndexData(NV_INDEX * nvIndex,UINT32 offset,UINT32 size,void * data)1073*5c591343SA. Cody Schuffelen NvWriteIndexData(
1074*5c591343SA. Cody Schuffelen NV_INDEX *nvIndex, // IN: the description of the index
1075*5c591343SA. Cody Schuffelen UINT32 offset, // IN: offset of NV data
1076*5c591343SA. Cody Schuffelen UINT32 size, // IN: size of NV data
1077*5c591343SA. Cody Schuffelen void *data // IN: data buffer
1078*5c591343SA. Cody Schuffelen )
1079*5c591343SA. Cody Schuffelen {
1080*5c591343SA. Cody Schuffelen TPM_RC result = TPM_RC_SUCCESS;
1081*5c591343SA. Cody Schuffelen //
1082*5c591343SA. Cody Schuffelen pAssert(nvIndex != NULL);
1083*5c591343SA. Cody Schuffelen // Make sure that this is dealing with the 'default' index.
1084*5c591343SA. Cody Schuffelen // Note: it is tempting to change the calling sequence so that the 'default' is
1085*5c591343SA. Cody Schuffelen // presumed.
1086*5c591343SA. Cody Schuffelen pAssert(nvIndex->publicArea.nvIndex == s_cachedNvIndex.publicArea.nvIndex);
1087*5c591343SA. Cody Schuffelen
1088*5c591343SA. Cody Schuffelen // Validate that write falls within range of the index
1089*5c591343SA. Cody Schuffelen pAssert(offset <= nvIndex->publicArea.dataSize
1090*5c591343SA. Cody Schuffelen && size <= (nvIndex->publicArea.dataSize - offset));
1091*5c591343SA. Cody Schuffelen
1092*5c591343SA. Cody Schuffelen // Update TPMA_NV_WRITTEN bit if necessary
1093*5c591343SA. Cody Schuffelen if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN))
1094*5c591343SA. Cody Schuffelen {
1095*5c591343SA. Cody Schuffelen // Update the in memory version of the attributes
1096*5c591343SA. Cody Schuffelen SET_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN);
1097*5c591343SA. Cody Schuffelen
1098*5c591343SA. Cody Schuffelen // If this is not orderly, then update the NV version of
1099*5c591343SA. Cody Schuffelen // the attributes
1100*5c591343SA. Cody Schuffelen if(!IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, ORDERLY))
1101*5c591343SA. Cody Schuffelen {
1102*5c591343SA. Cody Schuffelen result = NvWriteNvIndexAttributes(s_cachedNvRef,
1103*5c591343SA. Cody Schuffelen nvIndex->publicArea.attributes);
1104*5c591343SA. Cody Schuffelen if(result != TPM_RC_SUCCESS)
1105*5c591343SA. Cody Schuffelen return result;
1106*5c591343SA. Cody Schuffelen // If this is a partial write of an ordinary index, clear the whole
1107*5c591343SA. Cody Schuffelen // index.
1108*5c591343SA. Cody Schuffelen if(IsNvOrdinaryIndex(nvIndex->publicArea.attributes)
1109*5c591343SA. Cody Schuffelen && (nvIndex->publicArea.dataSize > size))
1110*5c591343SA. Cody Schuffelen _plat__NvMemoryClear(s_cachedNvRef + sizeof(NV_INDEX),
1111*5c591343SA. Cody Schuffelen nvIndex->publicArea.dataSize);
1112*5c591343SA. Cody Schuffelen }
1113*5c591343SA. Cody Schuffelen else
1114*5c591343SA. Cody Schuffelen {
1115*5c591343SA. Cody Schuffelen // This is orderly so update the RAM version
1116*5c591343SA. Cody Schuffelen MemoryCopy(s_cachedNvRamRef + offsetof(NV_RAM_HEADER, attributes),
1117*5c591343SA. Cody Schuffelen &nvIndex->publicArea.attributes, sizeof(TPMA_NV));
1118*5c591343SA. Cody Schuffelen // If setting WRITTEN for an orderly counter, make sure that the
1119*5c591343SA. Cody Schuffelen // state saved version of the counter is saved
1120*5c591343SA. Cody Schuffelen if(IsNvCounterIndex(nvIndex->publicArea.attributes))
1121*5c591343SA. Cody Schuffelen SET_NV_UPDATE(UT_ORDERLY);
1122*5c591343SA. Cody Schuffelen // If setting the written attribute on an ordinary index, make sure that
1123*5c591343SA. Cody Schuffelen // the data is all cleared out in case there is a partial write. This
1124*5c591343SA. Cody Schuffelen // is only necessary for ordinary indexes because all of the other types
1125*5c591343SA. Cody Schuffelen // are always written in total.
1126*5c591343SA. Cody Schuffelen else if(IsNvOrdinaryIndex(nvIndex->publicArea.attributes))
1127*5c591343SA. Cody Schuffelen MemorySet(s_cachedNvRamRef + sizeof(NV_RAM_HEADER),
1128*5c591343SA. Cody Schuffelen 0, nvIndex->publicArea.dataSize);
1129*5c591343SA. Cody Schuffelen }
1130*5c591343SA. Cody Schuffelen }
1131*5c591343SA. Cody Schuffelen // If this is orderly data, write it to RAM
1132*5c591343SA. Cody Schuffelen if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, ORDERLY))
1133*5c591343SA. Cody Schuffelen {
1134*5c591343SA. Cody Schuffelen // Note: if this is the first write to a counter, the code above will queue
1135*5c591343SA. Cody Schuffelen // the write to NV of the RAM data in order to update TPMA_NV_WRITTEN. In
1136*5c591343SA. Cody Schuffelen // process of doing that write, it will also write the initial counter value
1137*5c591343SA. Cody Schuffelen
1138*5c591343SA. Cody Schuffelen // Update RAM
1139*5c591343SA. Cody Schuffelen MemoryCopy(s_cachedNvRamRef + sizeof(NV_RAM_HEADER) + offset, data, size);
1140*5c591343SA. Cody Schuffelen
1141*5c591343SA. Cody Schuffelen // And indicate that the TPM is no longer orderly
1142*5c591343SA. Cody Schuffelen g_clearOrderly = TRUE;
1143*5c591343SA. Cody Schuffelen }
1144*5c591343SA. Cody Schuffelen else
1145*5c591343SA. Cody Schuffelen {
1146*5c591343SA. Cody Schuffelen // Offset into the index to the first byte of the data to be written to NV
1147*5c591343SA. Cody Schuffelen result = NvConditionallyWrite(s_cachedNvRef + sizeof(NV_INDEX) + offset,
1148*5c591343SA. Cody Schuffelen size, data);
1149*5c591343SA. Cody Schuffelen }
1150*5c591343SA. Cody Schuffelen return result;
1151*5c591343SA. Cody Schuffelen }
1152*5c591343SA. Cody Schuffelen
1153*5c591343SA. Cody Schuffelen //*** NvWriteUINT64Data()
1154*5c591343SA. Cody Schuffelen // This function to write back a UINT64 value. The various UINT64 values (bits,
1155*5c591343SA. Cody Schuffelen // counters, and PINs) are kept in canonical format but manipulate in native
1156*5c591343SA. Cody Schuffelen // format. This takes a native format value converts it and saves it back as
1157*5c591343SA. Cody Schuffelen // in canonical format.
1158*5c591343SA. Cody Schuffelen //
1159*5c591343SA. Cody Schuffelen // This function will return the value from NV or RAM depending on the type of the
1160*5c591343SA. Cody Schuffelen // index (orderly or not)
1161*5c591343SA. Cody Schuffelen //
1162*5c591343SA. Cody Schuffelen TPM_RC
NvWriteUINT64Data(NV_INDEX * nvIndex,UINT64 intValue)1163*5c591343SA. Cody Schuffelen NvWriteUINT64Data(
1164*5c591343SA. Cody Schuffelen NV_INDEX *nvIndex, // IN: the description of the index
1165*5c591343SA. Cody Schuffelen UINT64 intValue // IN: the value to write
1166*5c591343SA. Cody Schuffelen )
1167*5c591343SA. Cody Schuffelen {
1168*5c591343SA. Cody Schuffelen BYTE bytes[8];
1169*5c591343SA. Cody Schuffelen UINT64_TO_BYTE_ARRAY(intValue, bytes);
1170*5c591343SA. Cody Schuffelen //
1171*5c591343SA. Cody Schuffelen return NvWriteIndexData(nvIndex, 0, 8, &bytes);
1172*5c591343SA. Cody Schuffelen }
1173*5c591343SA. Cody Schuffelen
1174*5c591343SA. Cody Schuffelen //*** NvGetIndexName()
1175*5c591343SA. Cody Schuffelen // This function computes the Name of an index
1176*5c591343SA. Cody Schuffelen // The 'name' buffer receives the bytes of the Name and the return value
1177*5c591343SA. Cody Schuffelen // is the number of octets in the Name.
1178*5c591343SA. Cody Schuffelen //
1179*5c591343SA. Cody Schuffelen // This function requires that the NV Index is defined.
1180*5c591343SA. Cody Schuffelen TPM2B_NAME *
NvGetIndexName(NV_INDEX * nvIndex,TPM2B_NAME * name)1181*5c591343SA. Cody Schuffelen NvGetIndexName(
1182*5c591343SA. Cody Schuffelen NV_INDEX *nvIndex, // IN: the index over which the name is to be
1183*5c591343SA. Cody Schuffelen // computed
1184*5c591343SA. Cody Schuffelen TPM2B_NAME *name // OUT: name of the index
1185*5c591343SA. Cody Schuffelen )
1186*5c591343SA. Cody Schuffelen {
1187*5c591343SA. Cody Schuffelen UINT16 dataSize, digestSize;
1188*5c591343SA. Cody Schuffelen BYTE marshalBuffer[sizeof(TPMS_NV_PUBLIC)];
1189*5c591343SA. Cody Schuffelen BYTE *buffer;
1190*5c591343SA. Cody Schuffelen HASH_STATE hashState;
1191*5c591343SA. Cody Schuffelen //
1192*5c591343SA. Cody Schuffelen // Marshal public area
1193*5c591343SA. Cody Schuffelen buffer = marshalBuffer;
1194*5c591343SA. Cody Schuffelen dataSize = TPMS_NV_PUBLIC_Marshal(&nvIndex->publicArea, &buffer, NULL);
1195*5c591343SA. Cody Schuffelen
1196*5c591343SA. Cody Schuffelen // hash public area
1197*5c591343SA. Cody Schuffelen digestSize = CryptHashStart(&hashState, nvIndex->publicArea.nameAlg);
1198*5c591343SA. Cody Schuffelen CryptDigestUpdate(&hashState, dataSize, marshalBuffer);
1199*5c591343SA. Cody Schuffelen
1200*5c591343SA. Cody Schuffelen // Complete digest leaving room for the nameAlg
1201*5c591343SA. Cody Schuffelen CryptHashEnd(&hashState, digestSize, &name->b.buffer[2]);
1202*5c591343SA. Cody Schuffelen
1203*5c591343SA. Cody Schuffelen // Include the nameAlg
1204*5c591343SA. Cody Schuffelen UINT16_TO_BYTE_ARRAY(nvIndex->publicArea.nameAlg, name->b.buffer);
1205*5c591343SA. Cody Schuffelen name->t.size = digestSize + 2;
1206*5c591343SA. Cody Schuffelen return name;
1207*5c591343SA. Cody Schuffelen }
1208*5c591343SA. Cody Schuffelen
1209*5c591343SA. Cody Schuffelen //*** NvGetNameByIndexHandle()
1210*5c591343SA. Cody Schuffelen // This function is used to compute the Name of an NV Index referenced by handle.
1211*5c591343SA. Cody Schuffelen //
1212*5c591343SA. Cody Schuffelen // The 'name' buffer receives the bytes of the Name and the return value
1213*5c591343SA. Cody Schuffelen // is the number of octets in the Name.
1214*5c591343SA. Cody Schuffelen //
1215*5c591343SA. Cody Schuffelen // This function requires that the NV Index is defined.
1216*5c591343SA. Cody Schuffelen TPM2B_NAME *
NvGetNameByIndexHandle(TPMI_RH_NV_INDEX handle,TPM2B_NAME * name)1217*5c591343SA. Cody Schuffelen NvGetNameByIndexHandle(
1218*5c591343SA. Cody Schuffelen TPMI_RH_NV_INDEX handle, // IN: handle of the index
1219*5c591343SA. Cody Schuffelen TPM2B_NAME *name // OUT: name of the index
1220*5c591343SA. Cody Schuffelen )
1221*5c591343SA. Cody Schuffelen {
1222*5c591343SA. Cody Schuffelen NV_INDEX *nvIndex = NvGetIndexInfo(handle, NULL);
1223*5c591343SA. Cody Schuffelen //
1224*5c591343SA. Cody Schuffelen return NvGetIndexName(nvIndex, name);
1225*5c591343SA. Cody Schuffelen }
1226*5c591343SA. Cody Schuffelen
1227*5c591343SA. Cody Schuffelen //*** NvDefineIndex()
1228*5c591343SA. Cody Schuffelen // This function is used to assign NV memory to an NV Index.
1229*5c591343SA. Cody Schuffelen //
1230*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
1231*5c591343SA. Cody Schuffelen // TPM_RC_NV_SPACE insufficient NV space
1232*5c591343SA. Cody Schuffelen TPM_RC
NvDefineIndex(TPMS_NV_PUBLIC * publicArea,TPM2B_AUTH * authValue)1233*5c591343SA. Cody Schuffelen NvDefineIndex(
1234*5c591343SA. Cody Schuffelen TPMS_NV_PUBLIC *publicArea, // IN: A template for an area to create.
1235*5c591343SA. Cody Schuffelen TPM2B_AUTH *authValue // IN: The initial authorization value
1236*5c591343SA. Cody Schuffelen )
1237*5c591343SA. Cody Schuffelen {
1238*5c591343SA. Cody Schuffelen // The buffer to be written to NV memory
1239*5c591343SA. Cody Schuffelen NV_INDEX nvIndex; // the index data
1240*5c591343SA. Cody Schuffelen UINT16 entrySize; // size of entry
1241*5c591343SA. Cody Schuffelen TPM_RC result;
1242*5c591343SA. Cody Schuffelen //
1243*5c591343SA. Cody Schuffelen entrySize = sizeof(NV_INDEX);
1244*5c591343SA. Cody Schuffelen
1245*5c591343SA. Cody Schuffelen // only allocate data space for indexes that are going to be written to NV.
1246*5c591343SA. Cody Schuffelen // Orderly indexes don't need space.
1247*5c591343SA. Cody Schuffelen if(!IS_ATTRIBUTE(publicArea->attributes, TPMA_NV, ORDERLY))
1248*5c591343SA. Cody Schuffelen entrySize += publicArea->dataSize;
1249*5c591343SA. Cody Schuffelen // Check if we have enough space to create the NV Index
1250*5c591343SA. Cody Schuffelen // In this implementation, the only resource limitation is the available NV
1251*5c591343SA. Cody Schuffelen // space (and possibly RAM space.) Other implementation may have other
1252*5c591343SA. Cody Schuffelen // limitation on counter or on NV slots
1253*5c591343SA. Cody Schuffelen if(!NvTestSpace(entrySize, TRUE, IsNvCounterIndex(publicArea->attributes)))
1254*5c591343SA. Cody Schuffelen return TPM_RC_NV_SPACE;
1255*5c591343SA. Cody Schuffelen
1256*5c591343SA. Cody Schuffelen // if the index to be defined is RAM backed, check RAM space availability
1257*5c591343SA. Cody Schuffelen // as well
1258*5c591343SA. Cody Schuffelen if(IS_ATTRIBUTE(publicArea->attributes, TPMA_NV, ORDERLY)
1259*5c591343SA. Cody Schuffelen && !NvRamTestSpaceIndex(publicArea->dataSize))
1260*5c591343SA. Cody Schuffelen return TPM_RC_NV_SPACE;
1261*5c591343SA. Cody Schuffelen // Copy input value to nvBuffer
1262*5c591343SA. Cody Schuffelen nvIndex.publicArea = *publicArea;
1263*5c591343SA. Cody Schuffelen
1264*5c591343SA. Cody Schuffelen // Copy the authValue
1265*5c591343SA. Cody Schuffelen nvIndex.authValue = *authValue;
1266*5c591343SA. Cody Schuffelen
1267*5c591343SA. Cody Schuffelen // Add index to NV memory
1268*5c591343SA. Cody Schuffelen result = NvAdd(entrySize, sizeof(NV_INDEX), TPM_RH_UNASSIGNED,
1269*5c591343SA. Cody Schuffelen (BYTE *)&nvIndex);
1270*5c591343SA. Cody Schuffelen if(result == TPM_RC_SUCCESS)
1271*5c591343SA. Cody Schuffelen {
1272*5c591343SA. Cody Schuffelen // If the data of NV Index is RAM backed, add the data area in RAM as well
1273*5c591343SA. Cody Schuffelen if(IS_ATTRIBUTE(publicArea->attributes, TPMA_NV, ORDERLY))
1274*5c591343SA. Cody Schuffelen NvAddRAM(publicArea);
1275*5c591343SA. Cody Schuffelen }
1276*5c591343SA. Cody Schuffelen return result;
1277*5c591343SA. Cody Schuffelen }
1278*5c591343SA. Cody Schuffelen
1279*5c591343SA. Cody Schuffelen //*** NvAddEvictObject()
1280*5c591343SA. Cody Schuffelen // This function is used to assign NV memory to a persistent object.
1281*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
1282*5c591343SA. Cody Schuffelen // TPM_RC_NV_HANDLE the requested handle is already in use
1283*5c591343SA. Cody Schuffelen // TPM_RC_NV_SPACE insufficient NV space
1284*5c591343SA. Cody Schuffelen TPM_RC
NvAddEvictObject(TPMI_DH_OBJECT evictHandle,OBJECT * object)1285*5c591343SA. Cody Schuffelen NvAddEvictObject(
1286*5c591343SA. Cody Schuffelen TPMI_DH_OBJECT evictHandle, // IN: new evict handle
1287*5c591343SA. Cody Schuffelen OBJECT *object // IN: object to be added
1288*5c591343SA. Cody Schuffelen )
1289*5c591343SA. Cody Schuffelen {
1290*5c591343SA. Cody Schuffelen TPM_HANDLE temp = object->evictHandle;
1291*5c591343SA. Cody Schuffelen TPM_RC result;
1292*5c591343SA. Cody Schuffelen //
1293*5c591343SA. Cody Schuffelen // Check if we have enough space to add the evict object
1294*5c591343SA. Cody Schuffelen // An evict object needs 8 bytes in index table + sizeof OBJECT
1295*5c591343SA. Cody Schuffelen // In this implementation, the only resource limitation is the available NV
1296*5c591343SA. Cody Schuffelen // space. Other implementation may have other limitation on evict object
1297*5c591343SA. Cody Schuffelen // handle space
1298*5c591343SA. Cody Schuffelen if(!NvTestSpace(sizeof(OBJECT) + sizeof(TPM_HANDLE), FALSE, FALSE))
1299*5c591343SA. Cody Schuffelen return TPM_RC_NV_SPACE;
1300*5c591343SA. Cody Schuffelen
1301*5c591343SA. Cody Schuffelen // Set evict attribute and handle
1302*5c591343SA. Cody Schuffelen object->attributes.evict = SET;
1303*5c591343SA. Cody Schuffelen object->evictHandle = evictHandle;
1304*5c591343SA. Cody Schuffelen
1305*5c591343SA. Cody Schuffelen // Now put this in NV
1306*5c591343SA. Cody Schuffelen result = NvAdd(sizeof(OBJECT), sizeof(OBJECT), evictHandle, (BYTE *)object);
1307*5c591343SA. Cody Schuffelen
1308*5c591343SA. Cody Schuffelen // Put things back the way they were
1309*5c591343SA. Cody Schuffelen object->attributes.evict = CLEAR;
1310*5c591343SA. Cody Schuffelen object->evictHandle = temp;
1311*5c591343SA. Cody Schuffelen
1312*5c591343SA. Cody Schuffelen return result;
1313*5c591343SA. Cody Schuffelen }
1314*5c591343SA. Cody Schuffelen
1315*5c591343SA. Cody Schuffelen //*** NvDeleteIndex()
1316*5c591343SA. Cody Schuffelen // This function is used to delete an NV Index.
1317*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
1318*5c591343SA. Cody Schuffelen // TPM_RC_NV_UNAVAILABLE NV is not accessible
1319*5c591343SA. Cody Schuffelen // TPM_RC_NV_RATE NV is rate limiting
1320*5c591343SA. Cody Schuffelen TPM_RC
NvDeleteIndex(NV_INDEX * nvIndex,NV_REF entityAddr)1321*5c591343SA. Cody Schuffelen NvDeleteIndex(
1322*5c591343SA. Cody Schuffelen NV_INDEX *nvIndex, // IN: an in RAM index descriptor
1323*5c591343SA. Cody Schuffelen NV_REF entityAddr // IN: location in NV
1324*5c591343SA. Cody Schuffelen )
1325*5c591343SA. Cody Schuffelen {
1326*5c591343SA. Cody Schuffelen TPM_RC result;
1327*5c591343SA. Cody Schuffelen //
1328*5c591343SA. Cody Schuffelen if(nvIndex != NULL)
1329*5c591343SA. Cody Schuffelen {
1330*5c591343SA. Cody Schuffelen // Whenever a counter is deleted, make sure that the MaxCounter value is
1331*5c591343SA. Cody Schuffelen // updated to reflect the value
1332*5c591343SA. Cody Schuffelen if(IsNvCounterIndex(nvIndex->publicArea.attributes)
1333*5c591343SA. Cody Schuffelen && IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, WRITTEN))
1334*5c591343SA. Cody Schuffelen NvUpdateMaxCount(NvGetUINT64Data(nvIndex, entityAddr));
1335*5c591343SA. Cody Schuffelen result = NvDelete(entityAddr);
1336*5c591343SA. Cody Schuffelen if(result != TPM_RC_SUCCESS)
1337*5c591343SA. Cody Schuffelen return result;
1338*5c591343SA. Cody Schuffelen // If the NV Index is RAM backed, delete the RAM data as well
1339*5c591343SA. Cody Schuffelen if(IS_ATTRIBUTE(nvIndex->publicArea.attributes, TPMA_NV, ORDERLY))
1340*5c591343SA. Cody Schuffelen NvDeleteRAM(nvIndex->publicArea.nvIndex);
1341*5c591343SA. Cody Schuffelen NvIndexCacheInit();
1342*5c591343SA. Cody Schuffelen }
1343*5c591343SA. Cody Schuffelen return TPM_RC_SUCCESS;
1344*5c591343SA. Cody Schuffelen }
1345*5c591343SA. Cody Schuffelen
1346*5c591343SA. Cody Schuffelen //*** NvDeleteEvict()
1347*5c591343SA. Cody Schuffelen // This function will delete a NV evict object.
1348*5c591343SA. Cody Schuffelen // Will return success if object deleted or if it does not exist
1349*5c591343SA. Cody Schuffelen
1350*5c591343SA. Cody Schuffelen TPM_RC
NvDeleteEvict(TPM_HANDLE handle)1351*5c591343SA. Cody Schuffelen NvDeleteEvict(
1352*5c591343SA. Cody Schuffelen TPM_HANDLE handle // IN: handle of entity to be deleted
1353*5c591343SA. Cody Schuffelen )
1354*5c591343SA. Cody Schuffelen {
1355*5c591343SA. Cody Schuffelen NV_REF entityAddr = NvFindEvict(handle, NULL); // pointer to entity
1356*5c591343SA. Cody Schuffelen TPM_RC result = TPM_RC_SUCCESS;
1357*5c591343SA. Cody Schuffelen //
1358*5c591343SA. Cody Schuffelen if(entityAddr != 0)
1359*5c591343SA. Cody Schuffelen result = NvDelete(entityAddr);
1360*5c591343SA. Cody Schuffelen return result;
1361*5c591343SA. Cody Schuffelen }
1362*5c591343SA. Cody Schuffelen
1363*5c591343SA. Cody Schuffelen //*** NvFlushHierarchy()
1364*5c591343SA. Cody Schuffelen // This function will delete persistent objects belonging to the indicated hierarchy.
1365*5c591343SA. Cody Schuffelen // If the storage hierarchy is selected, the function will also delete any
1366*5c591343SA. Cody Schuffelen // NV Index defined using ownerAuth.
1367*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
1368*5c591343SA. Cody Schuffelen // TPM_RC_NV_RATE NV is unavailable because of rate limit
1369*5c591343SA. Cody Schuffelen // TPM_RC_NV_UNAVAILABLE NV is inaccessible
1370*5c591343SA. Cody Schuffelen TPM_RC
NvFlushHierarchy(TPMI_RH_HIERARCHY hierarchy)1371*5c591343SA. Cody Schuffelen NvFlushHierarchy(
1372*5c591343SA. Cody Schuffelen TPMI_RH_HIERARCHY hierarchy // IN: hierarchy to be flushed.
1373*5c591343SA. Cody Schuffelen )
1374*5c591343SA. Cody Schuffelen {
1375*5c591343SA. Cody Schuffelen NV_REF iter = NV_REF_INIT;
1376*5c591343SA. Cody Schuffelen NV_REF currentAddr;
1377*5c591343SA. Cody Schuffelen TPM_HANDLE entityHandle;
1378*5c591343SA. Cody Schuffelen TPM_RC result = TPM_RC_SUCCESS;
1379*5c591343SA. Cody Schuffelen //
1380*5c591343SA. Cody Schuffelen while((currentAddr = NvNext(&iter, &entityHandle)) != 0)
1381*5c591343SA. Cody Schuffelen {
1382*5c591343SA. Cody Schuffelen if(HandleGetType(entityHandle) == TPM_HT_NV_INDEX)
1383*5c591343SA. Cody Schuffelen {
1384*5c591343SA. Cody Schuffelen NV_INDEX nvIndex;
1385*5c591343SA. Cody Schuffelen //
1386*5c591343SA. Cody Schuffelen // If flush endorsement or platform hierarchy, no NV Index would be
1387*5c591343SA. Cody Schuffelen // flushed
1388*5c591343SA. Cody Schuffelen if(hierarchy == TPM_RH_ENDORSEMENT || hierarchy == TPM_RH_PLATFORM)
1389*5c591343SA. Cody Schuffelen continue;
1390*5c591343SA. Cody Schuffelen // Get the index information
1391*5c591343SA. Cody Schuffelen NvReadNvIndexInfo(currentAddr, &nvIndex);
1392*5c591343SA. Cody Schuffelen
1393*5c591343SA. Cody Schuffelen // For storage hierarchy, flush OwnerCreated index
1394*5c591343SA. Cody Schuffelen if(!IS_ATTRIBUTE(nvIndex.publicArea.attributes, TPMA_NV,
1395*5c591343SA. Cody Schuffelen PLATFORMCREATE))
1396*5c591343SA. Cody Schuffelen {
1397*5c591343SA. Cody Schuffelen // Delete the index (including RAM for orderly)
1398*5c591343SA. Cody Schuffelen result = NvDeleteIndex(&nvIndex, currentAddr);
1399*5c591343SA. Cody Schuffelen if(result != TPM_RC_SUCCESS)
1400*5c591343SA. Cody Schuffelen break;
1401*5c591343SA. Cody Schuffelen // Re-iterate from beginning after a delete
1402*5c591343SA. Cody Schuffelen iter = NV_REF_INIT;
1403*5c591343SA. Cody Schuffelen }
1404*5c591343SA. Cody Schuffelen }
1405*5c591343SA. Cody Schuffelen else if(HandleGetType(entityHandle) == TPM_HT_PERSISTENT)
1406*5c591343SA. Cody Schuffelen {
1407*5c591343SA. Cody Schuffelen OBJECT_ATTRIBUTES attributes;
1408*5c591343SA. Cody Schuffelen //
1409*5c591343SA. Cody Schuffelen NvRead(&attributes,
1410*5c591343SA. Cody Schuffelen (UINT32)(currentAddr
1411*5c591343SA. Cody Schuffelen + sizeof(TPM_HANDLE)
1412*5c591343SA. Cody Schuffelen + offsetof(OBJECT, attributes)),
1413*5c591343SA. Cody Schuffelen sizeof(OBJECT_ATTRIBUTES));
1414*5c591343SA. Cody Schuffelen // If the evict object belongs to the hierarchy to be flushed...
1415*5c591343SA. Cody Schuffelen if((hierarchy == TPM_RH_PLATFORM && attributes.ppsHierarchy == SET)
1416*5c591343SA. Cody Schuffelen || (hierarchy == TPM_RH_OWNER && attributes.spsHierarchy == SET)
1417*5c591343SA. Cody Schuffelen || (hierarchy == TPM_RH_ENDORSEMENT
1418*5c591343SA. Cody Schuffelen && attributes.epsHierarchy == SET))
1419*5c591343SA. Cody Schuffelen {
1420*5c591343SA. Cody Schuffelen // ...then delete the evict object
1421*5c591343SA. Cody Schuffelen result = NvDelete(currentAddr);
1422*5c591343SA. Cody Schuffelen if(result != TPM_RC_SUCCESS)
1423*5c591343SA. Cody Schuffelen break;
1424*5c591343SA. Cody Schuffelen // Re-iterate from beginning after a delete
1425*5c591343SA. Cody Schuffelen iter = NV_REF_INIT;
1426*5c591343SA. Cody Schuffelen }
1427*5c591343SA. Cody Schuffelen }
1428*5c591343SA. Cody Schuffelen else
1429*5c591343SA. Cody Schuffelen {
1430*5c591343SA. Cody Schuffelen FAIL(FATAL_ERROR_INTERNAL);
1431*5c591343SA. Cody Schuffelen }
1432*5c591343SA. Cody Schuffelen }
1433*5c591343SA. Cody Schuffelen return result;
1434*5c591343SA. Cody Schuffelen }
1435*5c591343SA. Cody Schuffelen
1436*5c591343SA. Cody Schuffelen //*** NvSetGlobalLock()
1437*5c591343SA. Cody Schuffelen // This function is used to SET the TPMA_NV_WRITELOCKED attribute for all
1438*5c591343SA. Cody Schuffelen // NV indexes that have TPMA_NV_GLOBALLOCK SET. This function is use by
1439*5c591343SA. Cody Schuffelen // TPM2_NV_GlobalWriteLock().
1440*5c591343SA. Cody Schuffelen // Return Type: TPM_RC
1441*5c591343SA. Cody Schuffelen // TPM_RC_NV_RATE NV is unavailable because of rate limit
1442*5c591343SA. Cody Schuffelen // TPM_RC_NV_UNAVAILABLE NV is inaccessible
1443*5c591343SA. Cody Schuffelen TPM_RC
NvSetGlobalLock(void)1444*5c591343SA. Cody Schuffelen NvSetGlobalLock(
1445*5c591343SA. Cody Schuffelen void
1446*5c591343SA. Cody Schuffelen )
1447*5c591343SA. Cody Schuffelen {
1448*5c591343SA. Cody Schuffelen NV_REF iter = NV_REF_INIT;
1449*5c591343SA. Cody Schuffelen NV_RAM_REF ramIter = NV_RAM_REF_INIT;
1450*5c591343SA. Cody Schuffelen NV_REF currentAddr;
1451*5c591343SA. Cody Schuffelen NV_RAM_REF currentRamAddr;
1452*5c591343SA. Cody Schuffelen TPM_RC result = TPM_RC_SUCCESS;
1453*5c591343SA. Cody Schuffelen //
1454*5c591343SA. Cody Schuffelen // Check all normal indexes
1455*5c591343SA. Cody Schuffelen while((currentAddr = NvNextIndex(NULL, &iter)) != 0)
1456*5c591343SA. Cody Schuffelen {
1457*5c591343SA. Cody Schuffelen TPMA_NV attributes = NvReadNvIndexAttributes(currentAddr);
1458*5c591343SA. Cody Schuffelen //
1459*5c591343SA. Cody Schuffelen // See if it should be locked
1460*5c591343SA. Cody Schuffelen if(!IS_ATTRIBUTE(attributes, TPMA_NV, ORDERLY)
1461*5c591343SA. Cody Schuffelen && IS_ATTRIBUTE(attributes, TPMA_NV, GLOBALLOCK))
1462*5c591343SA. Cody Schuffelen {
1463*5c591343SA. Cody Schuffelen SET_ATTRIBUTE(attributes, TPMA_NV, WRITELOCKED);
1464*5c591343SA. Cody Schuffelen result = NvWriteNvIndexAttributes(currentAddr, attributes);
1465*5c591343SA. Cody Schuffelen if(result != TPM_RC_SUCCESS)
1466*5c591343SA. Cody Schuffelen return result;
1467*5c591343SA. Cody Schuffelen }
1468*5c591343SA. Cody Schuffelen }
1469*5c591343SA. Cody Schuffelen // Now search all the orderly attributes
1470*5c591343SA. Cody Schuffelen while((currentRamAddr = NvRamNext(&ramIter, NULL)) != 0)
1471*5c591343SA. Cody Schuffelen {
1472*5c591343SA. Cody Schuffelen // See if it should be locked
1473*5c591343SA. Cody Schuffelen TPMA_NV attributes = NvReadRamIndexAttributes(currentRamAddr);
1474*5c591343SA. Cody Schuffelen if(IS_ATTRIBUTE(attributes, TPMA_NV, GLOBALLOCK))
1475*5c591343SA. Cody Schuffelen {
1476*5c591343SA. Cody Schuffelen SET_ATTRIBUTE(attributes, TPMA_NV, WRITELOCKED);
1477*5c591343SA. Cody Schuffelen NvWriteRamIndexAttributes(currentRamAddr, attributes);
1478*5c591343SA. Cody Schuffelen }
1479*5c591343SA. Cody Schuffelen }
1480*5c591343SA. Cody Schuffelen return result;
1481*5c591343SA. Cody Schuffelen }
1482*5c591343SA. Cody Schuffelen
1483*5c591343SA. Cody Schuffelen //***InsertSort()
1484*5c591343SA. Cody Schuffelen // Sort a handle into handle list in ascending order. The total handle number in
1485*5c591343SA. Cody Schuffelen // the list should not exceed MAX_CAP_HANDLES
1486*5c591343SA. Cody Schuffelen static void
InsertSort(TPML_HANDLE * handleList,UINT32 count,TPM_HANDLE entityHandle)1487*5c591343SA. Cody Schuffelen InsertSort(
1488*5c591343SA. Cody Schuffelen TPML_HANDLE *handleList, // IN/OUT: sorted handle list
1489*5c591343SA. Cody Schuffelen UINT32 count, // IN: maximum count in the handle list
1490*5c591343SA. Cody Schuffelen TPM_HANDLE entityHandle // IN: handle to be inserted
1491*5c591343SA. Cody Schuffelen )
1492*5c591343SA. Cody Schuffelen {
1493*5c591343SA. Cody Schuffelen UINT32 i, j;
1494*5c591343SA. Cody Schuffelen UINT32 originalCount;
1495*5c591343SA. Cody Schuffelen //
1496*5c591343SA. Cody Schuffelen // For a corner case that the maximum count is 0, do nothing
1497*5c591343SA. Cody Schuffelen if(count == 0)
1498*5c591343SA. Cody Schuffelen return;
1499*5c591343SA. Cody Schuffelen // For empty list, add the handle at the beginning and return
1500*5c591343SA. Cody Schuffelen if(handleList->count == 0)
1501*5c591343SA. Cody Schuffelen {
1502*5c591343SA. Cody Schuffelen handleList->handle[0] = entityHandle;
1503*5c591343SA. Cody Schuffelen handleList->count++;
1504*5c591343SA. Cody Schuffelen return;
1505*5c591343SA. Cody Schuffelen }
1506*5c591343SA. Cody Schuffelen // Check if the maximum of the list has been reached
1507*5c591343SA. Cody Schuffelen originalCount = handleList->count;
1508*5c591343SA. Cody Schuffelen if(originalCount < count)
1509*5c591343SA. Cody Schuffelen handleList->count++;
1510*5c591343SA. Cody Schuffelen // Insert the handle to the list
1511*5c591343SA. Cody Schuffelen for(i = 0; i < originalCount; i++)
1512*5c591343SA. Cody Schuffelen {
1513*5c591343SA. Cody Schuffelen if(handleList->handle[i] > entityHandle)
1514*5c591343SA. Cody Schuffelen {
1515*5c591343SA. Cody Schuffelen for(j = handleList->count - 1; j > i; j--)
1516*5c591343SA. Cody Schuffelen {
1517*5c591343SA. Cody Schuffelen handleList->handle[j] = handleList->handle[j - 1];
1518*5c591343SA. Cody Schuffelen }
1519*5c591343SA. Cody Schuffelen break;
1520*5c591343SA. Cody Schuffelen }
1521*5c591343SA. Cody Schuffelen }
1522*5c591343SA. Cody Schuffelen // If a slot was found, insert the handle in this position
1523*5c591343SA. Cody Schuffelen if(i < originalCount || handleList->count > originalCount)
1524*5c591343SA. Cody Schuffelen handleList->handle[i] = entityHandle;
1525*5c591343SA. Cody Schuffelen return;
1526*5c591343SA. Cody Schuffelen }
1527*5c591343SA. Cody Schuffelen
1528*5c591343SA. Cody Schuffelen //*** NvCapGetPersistent()
1529*5c591343SA. Cody Schuffelen // This function is used to get a list of handles of the persistent objects,
1530*5c591343SA. Cody Schuffelen // starting at 'handle'.
1531*5c591343SA. Cody Schuffelen //
1532*5c591343SA. Cody Schuffelen // 'Handle' must be in valid persistent object handle range, but does not
1533*5c591343SA. Cody Schuffelen // have to reference an existing persistent object.
1534*5c591343SA. Cody Schuffelen // Return Type: TPMI_YES_NO
1535*5c591343SA. Cody Schuffelen // YES if there are more handles available
1536*5c591343SA. Cody Schuffelen // NO all the available handles has been returned
1537*5c591343SA. Cody Schuffelen TPMI_YES_NO
NvCapGetPersistent(TPMI_DH_OBJECT handle,UINT32 count,TPML_HANDLE * handleList)1538*5c591343SA. Cody Schuffelen NvCapGetPersistent(
1539*5c591343SA. Cody Schuffelen TPMI_DH_OBJECT handle, // IN: start handle
1540*5c591343SA. Cody Schuffelen UINT32 count, // IN: maximum number of returned handles
1541*5c591343SA. Cody Schuffelen TPML_HANDLE *handleList // OUT: list of handle
1542*5c591343SA. Cody Schuffelen )
1543*5c591343SA. Cody Schuffelen {
1544*5c591343SA. Cody Schuffelen TPMI_YES_NO more = NO;
1545*5c591343SA. Cody Schuffelen NV_REF iter = NV_REF_INIT;
1546*5c591343SA. Cody Schuffelen NV_REF currentAddr;
1547*5c591343SA. Cody Schuffelen TPM_HANDLE entityHandle;
1548*5c591343SA. Cody Schuffelen //
1549*5c591343SA. Cody Schuffelen pAssert(HandleGetType(handle) == TPM_HT_PERSISTENT);
1550*5c591343SA. Cody Schuffelen
1551*5c591343SA. Cody Schuffelen // Initialize output handle list
1552*5c591343SA. Cody Schuffelen handleList->count = 0;
1553*5c591343SA. Cody Schuffelen
1554*5c591343SA. Cody Schuffelen // The maximum count of handles we may return is MAX_CAP_HANDLES
1555*5c591343SA. Cody Schuffelen if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;
1556*5c591343SA. Cody Schuffelen
1557*5c591343SA. Cody Schuffelen while((currentAddr = NvNextEvict(&entityHandle, &iter)) != 0)
1558*5c591343SA. Cody Schuffelen {
1559*5c591343SA. Cody Schuffelen // Ignore persistent handles that have values less than the input handle
1560*5c591343SA. Cody Schuffelen if(entityHandle < handle)
1561*5c591343SA. Cody Schuffelen continue;
1562*5c591343SA. Cody Schuffelen // if the handles in the list have reached the requested count, and there
1563*5c591343SA. Cody Schuffelen // are still handles need to be inserted, indicate that there are more.
1564*5c591343SA. Cody Schuffelen if(handleList->count == count)
1565*5c591343SA. Cody Schuffelen more = YES;
1566*5c591343SA. Cody Schuffelen // A handle with a value larger than start handle is a candidate
1567*5c591343SA. Cody Schuffelen // for return. Insert sort it to the return list. Insert sort algorithm
1568*5c591343SA. Cody Schuffelen // is chosen here for simplicity based on the assumption that the total
1569*5c591343SA. Cody Schuffelen // number of NV indexes is small. For an implementation that may allow
1570*5c591343SA. Cody Schuffelen // large number of NV indexes, a more efficient sorting algorithm may be
1571*5c591343SA. Cody Schuffelen // used here.
1572*5c591343SA. Cody Schuffelen InsertSort(handleList, count, entityHandle);
1573*5c591343SA. Cody Schuffelen }
1574*5c591343SA. Cody Schuffelen return more;
1575*5c591343SA. Cody Schuffelen }
1576*5c591343SA. Cody Schuffelen
1577*5c591343SA. Cody Schuffelen //*** NvCapGetIndex()
1578*5c591343SA. Cody Schuffelen // This function returns a list of handles of NV indexes, starting from 'handle'.
1579*5c591343SA. Cody Schuffelen // 'Handle' must be in the range of NV indexes, but does not have to reference
1580*5c591343SA. Cody Schuffelen // an existing NV Index.
1581*5c591343SA. Cody Schuffelen // Return Type: TPMI_YES_NO
1582*5c591343SA. Cody Schuffelen // YES if there are more handles to report
1583*5c591343SA. Cody Schuffelen // NO all the available handles has been reported
1584*5c591343SA. Cody Schuffelen TPMI_YES_NO
NvCapGetIndex(TPMI_DH_OBJECT handle,UINT32 count,TPML_HANDLE * handleList)1585*5c591343SA. Cody Schuffelen NvCapGetIndex(
1586*5c591343SA. Cody Schuffelen TPMI_DH_OBJECT handle, // IN: start handle
1587*5c591343SA. Cody Schuffelen UINT32 count, // IN: max number of returned handles
1588*5c591343SA. Cody Schuffelen TPML_HANDLE *handleList // OUT: list of handle
1589*5c591343SA. Cody Schuffelen )
1590*5c591343SA. Cody Schuffelen {
1591*5c591343SA. Cody Schuffelen TPMI_YES_NO more = NO;
1592*5c591343SA. Cody Schuffelen NV_REF iter = NV_REF_INIT;
1593*5c591343SA. Cody Schuffelen NV_REF currentAddr;
1594*5c591343SA. Cody Schuffelen TPM_HANDLE nvHandle;
1595*5c591343SA. Cody Schuffelen //
1596*5c591343SA. Cody Schuffelen pAssert(HandleGetType(handle) == TPM_HT_NV_INDEX);
1597*5c591343SA. Cody Schuffelen
1598*5c591343SA. Cody Schuffelen // Initialize output handle list
1599*5c591343SA. Cody Schuffelen handleList->count = 0;
1600*5c591343SA. Cody Schuffelen
1601*5c591343SA. Cody Schuffelen // The maximum count of handles we may return is MAX_CAP_HANDLES
1602*5c591343SA. Cody Schuffelen if(count > MAX_CAP_HANDLES) count = MAX_CAP_HANDLES;
1603*5c591343SA. Cody Schuffelen
1604*5c591343SA. Cody Schuffelen while((currentAddr = NvNextIndex(&nvHandle, &iter)) != 0)
1605*5c591343SA. Cody Schuffelen {
1606*5c591343SA. Cody Schuffelen // Ignore index handles that have values less than the 'handle'
1607*5c591343SA. Cody Schuffelen if(nvHandle < handle)
1608*5c591343SA. Cody Schuffelen continue;
1609*5c591343SA. Cody Schuffelen // if the count of handles in the list has reached the requested count,
1610*5c591343SA. Cody Schuffelen // and there are still handles to report, set more.
1611*5c591343SA. Cody Schuffelen if(handleList->count == count)
1612*5c591343SA. Cody Schuffelen more = YES;
1613*5c591343SA. Cody Schuffelen // A handle with a value larger than start handle is a candidate
1614*5c591343SA. Cody Schuffelen // for return. Insert sort it to the return list. Insert sort algorithm
1615*5c591343SA. Cody Schuffelen // is chosen here for simplicity based on the assumption that the total
1616*5c591343SA. Cody Schuffelen // number of NV indexes is small. For an implementation that may allow
1617*5c591343SA. Cody Schuffelen // large number of NV indexes, a more efficient sorting algorithm may be
1618*5c591343SA. Cody Schuffelen // used here.
1619*5c591343SA. Cody Schuffelen InsertSort(handleList, count, nvHandle);
1620*5c591343SA. Cody Schuffelen }
1621*5c591343SA. Cody Schuffelen return more;
1622*5c591343SA. Cody Schuffelen }
1623*5c591343SA. Cody Schuffelen
1624*5c591343SA. Cody Schuffelen //*** NvCapGetIndexNumber()
1625*5c591343SA. Cody Schuffelen // This function returns the count of NV Indexes currently defined.
1626*5c591343SA. Cody Schuffelen UINT32
NvCapGetIndexNumber(void)1627*5c591343SA. Cody Schuffelen NvCapGetIndexNumber(
1628*5c591343SA. Cody Schuffelen void
1629*5c591343SA. Cody Schuffelen )
1630*5c591343SA. Cody Schuffelen {
1631*5c591343SA. Cody Schuffelen UINT32 num = 0;
1632*5c591343SA. Cody Schuffelen NV_REF iter = NV_REF_INIT;
1633*5c591343SA. Cody Schuffelen //
1634*5c591343SA. Cody Schuffelen while(NvNextIndex(NULL, &iter) != 0)
1635*5c591343SA. Cody Schuffelen num++;
1636*5c591343SA. Cody Schuffelen return num;
1637*5c591343SA. Cody Schuffelen }
1638*5c591343SA. Cody Schuffelen
1639*5c591343SA. Cody Schuffelen //*** NvCapGetPersistentNumber()
1640*5c591343SA. Cody Schuffelen // Function returns the count of persistent objects currently in NV memory.
1641*5c591343SA. Cody Schuffelen UINT32
NvCapGetPersistentNumber(void)1642*5c591343SA. Cody Schuffelen NvCapGetPersistentNumber(
1643*5c591343SA. Cody Schuffelen void
1644*5c591343SA. Cody Schuffelen )
1645*5c591343SA. Cody Schuffelen {
1646*5c591343SA. Cody Schuffelen UINT32 num = 0;
1647*5c591343SA. Cody Schuffelen NV_REF iter = NV_REF_INIT;
1648*5c591343SA. Cody Schuffelen TPM_HANDLE handle;
1649*5c591343SA. Cody Schuffelen //
1650*5c591343SA. Cody Schuffelen while(NvNextEvict(&handle, &iter) != 0)
1651*5c591343SA. Cody Schuffelen num++;
1652*5c591343SA. Cody Schuffelen return num;
1653*5c591343SA. Cody Schuffelen }
1654*5c591343SA. Cody Schuffelen
1655*5c591343SA. Cody Schuffelen //*** NvCapGetPersistentAvail()
1656*5c591343SA. Cody Schuffelen // This function returns an estimate of the number of additional persistent
1657*5c591343SA. Cody Schuffelen // objects that could be loaded into NV memory.
1658*5c591343SA. Cody Schuffelen UINT32
NvCapGetPersistentAvail(void)1659*5c591343SA. Cody Schuffelen NvCapGetPersistentAvail(
1660*5c591343SA. Cody Schuffelen void
1661*5c591343SA. Cody Schuffelen )
1662*5c591343SA. Cody Schuffelen {
1663*5c591343SA. Cody Schuffelen UINT32 availNVSpace;
1664*5c591343SA. Cody Schuffelen UINT32 counterNum = NvCapGetCounterNumber();
1665*5c591343SA. Cody Schuffelen UINT32 reserved = sizeof(NV_LIST_TERMINATOR);
1666*5c591343SA. Cody Schuffelen //
1667*5c591343SA. Cody Schuffelen // Get the available space in NV storage
1668*5c591343SA. Cody Schuffelen availNVSpace = NvGetFreeBytes();
1669*5c591343SA. Cody Schuffelen
1670*5c591343SA. Cody Schuffelen if(counterNum < MIN_COUNTER_INDICES)
1671*5c591343SA. Cody Schuffelen {
1672*5c591343SA. Cody Schuffelen // Some space has to be reserved for counter objects.
1673*5c591343SA. Cody Schuffelen reserved += (MIN_COUNTER_INDICES - counterNum) * NV_INDEX_COUNTER_SIZE;
1674*5c591343SA. Cody Schuffelen if(reserved > availNVSpace)
1675*5c591343SA. Cody Schuffelen availNVSpace = 0;
1676*5c591343SA. Cody Schuffelen else
1677*5c591343SA. Cody Schuffelen availNVSpace -= reserved;
1678*5c591343SA. Cody Schuffelen }
1679*5c591343SA. Cody Schuffelen return availNVSpace / NV_EVICT_OBJECT_SIZE;
1680*5c591343SA. Cody Schuffelen }
1681*5c591343SA. Cody Schuffelen
1682*5c591343SA. Cody Schuffelen //*** NvCapGetCounterNumber()
1683*5c591343SA. Cody Schuffelen // Get the number of defined NV Indexes that are counter indexes.
1684*5c591343SA. Cody Schuffelen UINT32
NvCapGetCounterNumber(void)1685*5c591343SA. Cody Schuffelen NvCapGetCounterNumber(
1686*5c591343SA. Cody Schuffelen void
1687*5c591343SA. Cody Schuffelen )
1688*5c591343SA. Cody Schuffelen {
1689*5c591343SA. Cody Schuffelen NV_REF iter = NV_REF_INIT;
1690*5c591343SA. Cody Schuffelen NV_REF currentAddr;
1691*5c591343SA. Cody Schuffelen UINT32 num = 0;
1692*5c591343SA. Cody Schuffelen //
1693*5c591343SA. Cody Schuffelen while((currentAddr = NvNextIndex(NULL, &iter)) != 0)
1694*5c591343SA. Cody Schuffelen {
1695*5c591343SA. Cody Schuffelen TPMA_NV attributes = NvReadNvIndexAttributes(currentAddr);
1696*5c591343SA. Cody Schuffelen if(IsNvCounterIndex(attributes))
1697*5c591343SA. Cody Schuffelen num++;
1698*5c591343SA. Cody Schuffelen }
1699*5c591343SA. Cody Schuffelen return num;
1700*5c591343SA. Cody Schuffelen }
1701*5c591343SA. Cody Schuffelen
1702*5c591343SA. Cody Schuffelen //*** NvSetStartupAttributes()
1703*5c591343SA. Cody Schuffelen // Local function to set the attributes of an Index at TPM Reset and TPM Restart.
1704*5c591343SA. Cody Schuffelen static TPMA_NV
NvSetStartupAttributes(TPMA_NV attributes,STARTUP_TYPE type)1705*5c591343SA. Cody Schuffelen NvSetStartupAttributes(
1706*5c591343SA. Cody Schuffelen TPMA_NV attributes, // IN: attributes to change
1707*5c591343SA. Cody Schuffelen STARTUP_TYPE type // IN: start up type
1708*5c591343SA. Cody Schuffelen )
1709*5c591343SA. Cody Schuffelen {
1710*5c591343SA. Cody Schuffelen // Clear read lock
1711*5c591343SA. Cody Schuffelen CLEAR_ATTRIBUTE(attributes, TPMA_NV, READLOCKED);
1712*5c591343SA. Cody Schuffelen
1713*5c591343SA. Cody Schuffelen // Will change a non counter index to the unwritten state if:
1714*5c591343SA. Cody Schuffelen // a) TPMA_NV_CLEAR_STCLEAR is SET
1715*5c591343SA. Cody Schuffelen // b) orderly and TPM Reset
1716*5c591343SA. Cody Schuffelen if(!IsNvCounterIndex(attributes))
1717*5c591343SA. Cody Schuffelen {
1718*5c591343SA. Cody Schuffelen if(IS_ATTRIBUTE(attributes, TPMA_NV, CLEAR_STCLEAR)
1719*5c591343SA. Cody Schuffelen || (IS_ATTRIBUTE(attributes, TPMA_NV, ORDERLY)
1720*5c591343SA. Cody Schuffelen && (type == SU_RESET)))
1721*5c591343SA. Cody Schuffelen CLEAR_ATTRIBUTE(attributes, TPMA_NV, WRITTEN);
1722*5c591343SA. Cody Schuffelen }
1723*5c591343SA. Cody Schuffelen // Unlock any index that is not written or that does not have
1724*5c591343SA. Cody Schuffelen // TPMA_NV_WRITEDEFINE SET.
1725*5c591343SA. Cody Schuffelen if(!IS_ATTRIBUTE(attributes, TPMA_NV, WRITTEN)
1726*5c591343SA. Cody Schuffelen || !IS_ATTRIBUTE(attributes, TPMA_NV, WRITEDEFINE))
1727*5c591343SA. Cody Schuffelen CLEAR_ATTRIBUTE(attributes, TPMA_NV, WRITELOCKED);
1728*5c591343SA. Cody Schuffelen return attributes;
1729*5c591343SA. Cody Schuffelen }
1730*5c591343SA. Cody Schuffelen
1731*5c591343SA. Cody Schuffelen //*** NvEntityStartup()
1732*5c591343SA. Cody Schuffelen // This function is called at TPM_Startup(). If the startup completes
1733*5c591343SA. Cody Schuffelen // a TPM Resume cycle, no action is taken. If the startup is a TPM Reset
1734*5c591343SA. Cody Schuffelen // or a TPM Restart, then this function will:
1735*5c591343SA. Cody Schuffelen // a) clear read/write lock;
1736*5c591343SA. Cody Schuffelen // b) reset NV Index data that has TPMA_NV_CLEAR_STCLEAR SET; and
1737*5c591343SA. Cody Schuffelen // c) set the lower bits in orderly counters to 1 for a non-orderly startup
1738*5c591343SA. Cody Schuffelen //
1739*5c591343SA. Cody Schuffelen // It is a prerequisite that NV be available for writing before this
1740*5c591343SA. Cody Schuffelen // function is called.
1741*5c591343SA. Cody Schuffelen BOOL
NvEntityStartup(STARTUP_TYPE type)1742*5c591343SA. Cody Schuffelen NvEntityStartup(
1743*5c591343SA. Cody Schuffelen STARTUP_TYPE type // IN: start up type
1744*5c591343SA. Cody Schuffelen )
1745*5c591343SA. Cody Schuffelen {
1746*5c591343SA. Cody Schuffelen NV_REF iter = NV_REF_INIT;
1747*5c591343SA. Cody Schuffelen NV_RAM_REF ramIter = NV_RAM_REF_INIT;
1748*5c591343SA. Cody Schuffelen NV_REF currentAddr; // offset points to the current entity
1749*5c591343SA. Cody Schuffelen NV_RAM_REF currentRamAddr;
1750*5c591343SA. Cody Schuffelen TPM_HANDLE nvHandle;
1751*5c591343SA. Cody Schuffelen TPMA_NV attributes;
1752*5c591343SA. Cody Schuffelen //
1753*5c591343SA. Cody Schuffelen // Restore RAM index data
1754*5c591343SA. Cody Schuffelen NvRead(s_indexOrderlyRam, NV_INDEX_RAM_DATA, sizeof(s_indexOrderlyRam));
1755*5c591343SA. Cody Schuffelen
1756*5c591343SA. Cody Schuffelen // Initialize the max NV counter value
1757*5c591343SA. Cody Schuffelen NvSetMaxCount(NvGetMaxCount());
1758*5c591343SA. Cody Schuffelen
1759*5c591343SA. Cody Schuffelen // If recovering from state save, do nothing else
1760*5c591343SA. Cody Schuffelen if(type == SU_RESUME)
1761*5c591343SA. Cody Schuffelen return TRUE;
1762*5c591343SA. Cody Schuffelen // Iterate all the NV Index to clear the locks
1763*5c591343SA. Cody Schuffelen while((currentAddr = NvNextIndex(&nvHandle, &iter)) != 0)
1764*5c591343SA. Cody Schuffelen {
1765*5c591343SA. Cody Schuffelen attributes = NvReadNvIndexAttributes(currentAddr);
1766*5c591343SA. Cody Schuffelen
1767*5c591343SA. Cody Schuffelen // If this is an orderly index, defer processing until loop below
1768*5c591343SA. Cody Schuffelen if(IS_ATTRIBUTE(attributes, TPMA_NV, ORDERLY))
1769*5c591343SA. Cody Schuffelen continue;
1770*5c591343SA. Cody Schuffelen // Set the attributes appropriate for this startup type
1771*5c591343SA. Cody Schuffelen attributes = NvSetStartupAttributes(attributes, type);
1772*5c591343SA. Cody Schuffelen NvWriteNvIndexAttributes(currentAddr, attributes);
1773*5c591343SA. Cody Schuffelen }
1774*5c591343SA. Cody Schuffelen // Iterate all the orderly indexes to clear the locks and initialize counters
1775*5c591343SA. Cody Schuffelen while((currentRamAddr = NvRamNext(&ramIter, NULL)) != 0)
1776*5c591343SA. Cody Schuffelen {
1777*5c591343SA. Cody Schuffelen attributes = NvReadRamIndexAttributes(currentRamAddr);
1778*5c591343SA. Cody Schuffelen
1779*5c591343SA. Cody Schuffelen attributes = NvSetStartupAttributes(attributes, type);
1780*5c591343SA. Cody Schuffelen
1781*5c591343SA. Cody Schuffelen // update attributes in RAM
1782*5c591343SA. Cody Schuffelen NvWriteRamIndexAttributes(currentRamAddr, attributes);
1783*5c591343SA. Cody Schuffelen
1784*5c591343SA. Cody Schuffelen // Set the lower bits in an orderly counter to 1 for a non-orderly startup
1785*5c591343SA. Cody Schuffelen if(IsNvCounterIndex(attributes)
1786*5c591343SA. Cody Schuffelen && (g_prevOrderlyState == SU_NONE_VALUE))
1787*5c591343SA. Cody Schuffelen {
1788*5c591343SA. Cody Schuffelen UINT64 counter;
1789*5c591343SA. Cody Schuffelen //
1790*5c591343SA. Cody Schuffelen // Read the counter value last saved to NV.
1791*5c591343SA. Cody Schuffelen counter = BYTE_ARRAY_TO_UINT64(currentRamAddr + sizeof(NV_RAM_HEADER));
1792*5c591343SA. Cody Schuffelen
1793*5c591343SA. Cody Schuffelen // Set the lower bits of counter to 1's
1794*5c591343SA. Cody Schuffelen counter |= MAX_ORDERLY_COUNT;
1795*5c591343SA. Cody Schuffelen
1796*5c591343SA. Cody Schuffelen // Write back to RAM
1797*5c591343SA. Cody Schuffelen // NOTE: Do not want to force a write to NV here. The counter value will
1798*5c591343SA. Cody Schuffelen // stay in RAM until the next shutdown or rollover.
1799*5c591343SA. Cody Schuffelen UINT64_TO_BYTE_ARRAY(counter, currentRamAddr + sizeof(NV_RAM_HEADER));
1800*5c591343SA. Cody Schuffelen }
1801*5c591343SA. Cody Schuffelen }
1802*5c591343SA. Cody Schuffelen return TRUE;
1803*5c591343SA. Cody Schuffelen }
1804*5c591343SA. Cody Schuffelen
1805*5c591343SA. Cody Schuffelen //*** NvCapGetCounterAvail()
1806*5c591343SA. Cody Schuffelen // This function returns an estimate of the number of additional counter type
1807*5c591343SA. Cody Schuffelen // NV indexes that can be defined.
1808*5c591343SA. Cody Schuffelen UINT32
NvCapGetCounterAvail(void)1809*5c591343SA. Cody Schuffelen NvCapGetCounterAvail(
1810*5c591343SA. Cody Schuffelen void
1811*5c591343SA. Cody Schuffelen )
1812*5c591343SA. Cody Schuffelen {
1813*5c591343SA. Cody Schuffelen UINT32 availNVSpace;
1814*5c591343SA. Cody Schuffelen UINT32 availRAMSpace;
1815*5c591343SA. Cody Schuffelen UINT32 persistentNum = NvCapGetPersistentNumber();
1816*5c591343SA. Cody Schuffelen UINT32 reserved = sizeof(NV_LIST_TERMINATOR);
1817*5c591343SA. Cody Schuffelen //
1818*5c591343SA. Cody Schuffelen // Get the available space in NV storage
1819*5c591343SA. Cody Schuffelen availNVSpace = NvGetFreeBytes();
1820*5c591343SA. Cody Schuffelen
1821*5c591343SA. Cody Schuffelen if(persistentNum < MIN_EVICT_OBJECTS)
1822*5c591343SA. Cody Schuffelen {
1823*5c591343SA. Cody Schuffelen // Some space has to be reserved for evict object. Adjust availNVSpace.
1824*5c591343SA. Cody Schuffelen reserved += (MIN_EVICT_OBJECTS - persistentNum) * NV_EVICT_OBJECT_SIZE;
1825*5c591343SA. Cody Schuffelen if(reserved > availNVSpace)
1826*5c591343SA. Cody Schuffelen availNVSpace = 0;
1827*5c591343SA. Cody Schuffelen else
1828*5c591343SA. Cody Schuffelen availNVSpace -= reserved;
1829*5c591343SA. Cody Schuffelen }
1830*5c591343SA. Cody Schuffelen // Compute the available space in RAM
1831*5c591343SA. Cody Schuffelen availRAMSpace = (int)(RAM_ORDERLY_END - NvRamGetEnd());
1832*5c591343SA. Cody Schuffelen
1833*5c591343SA. Cody Schuffelen // Return the min of counter number in NV and in RAM
1834*5c591343SA. Cody Schuffelen if(availNVSpace / NV_INDEX_COUNTER_SIZE
1835*5c591343SA. Cody Schuffelen > availRAMSpace / NV_RAM_INDEX_COUNTER_SIZE)
1836*5c591343SA. Cody Schuffelen return availRAMSpace / NV_RAM_INDEX_COUNTER_SIZE;
1837*5c591343SA. Cody Schuffelen else
1838*5c591343SA. Cody Schuffelen return availNVSpace / NV_INDEX_COUNTER_SIZE;
1839*5c591343SA. Cody Schuffelen }
1840*5c591343SA. Cody Schuffelen
1841*5c591343SA. Cody Schuffelen //*** NvFindHandle()
1842*5c591343SA. Cody Schuffelen // this function returns the offset in NV memory of the entity associated
1843*5c591343SA. Cody Schuffelen // with the input handle. A value of zero indicates that handle does not
1844*5c591343SA. Cody Schuffelen // exist reference an existing persistent object or defined NV Index.
1845*5c591343SA. Cody Schuffelen NV_REF
NvFindHandle(TPM_HANDLE handle)1846*5c591343SA. Cody Schuffelen NvFindHandle(
1847*5c591343SA. Cody Schuffelen TPM_HANDLE handle
1848*5c591343SA. Cody Schuffelen )
1849*5c591343SA. Cody Schuffelen {
1850*5c591343SA. Cody Schuffelen NV_REF addr;
1851*5c591343SA. Cody Schuffelen NV_REF iter = NV_REF_INIT;
1852*5c591343SA. Cody Schuffelen TPM_HANDLE nextHandle;
1853*5c591343SA. Cody Schuffelen //
1854*5c591343SA. Cody Schuffelen while((addr = NvNext(&iter, &nextHandle)) != 0)
1855*5c591343SA. Cody Schuffelen {
1856*5c591343SA. Cody Schuffelen if(nextHandle == handle)
1857*5c591343SA. Cody Schuffelen break;
1858*5c591343SA. Cody Schuffelen }
1859*5c591343SA. Cody Schuffelen return addr;
1860*5c591343SA. Cody Schuffelen }
1861*5c591343SA. Cody Schuffelen
1862*5c591343SA. Cody Schuffelen //** NV Max Counter
1863*5c591343SA. Cody Schuffelen //*** Introduction
1864*5c591343SA. Cody Schuffelen // The TPM keeps track of the highest value of a deleted counter index. When an
1865*5c591343SA. Cody Schuffelen // index is deleted, this value is updated if the deleted counter index is greater
1866*5c591343SA. Cody Schuffelen // than the previous value. When a new index is created and first incremented, it
1867*5c591343SA. Cody Schuffelen // will get a value that is at least one greater than any other index than any
1868*5c591343SA. Cody Schuffelen // previously deleted index. This insures that it is not possible to roll back an
1869*5c591343SA. Cody Schuffelen // index.
1870*5c591343SA. Cody Schuffelen //
1871*5c591343SA. Cody Schuffelen // The highest counter value is kept in NV in a special end-of-list marker. This
1872*5c591343SA. Cody Schuffelen // marker is only updated when an index is deleted. Otherwise it just moves.
1873*5c591343SA. Cody Schuffelen //
1874*5c591343SA. Cody Schuffelen // When the TPM starts up, it searches NV for the end of list marker and initializes
1875*5c591343SA. Cody Schuffelen // an in memory value (s_maxCounter).
1876*5c591343SA. Cody Schuffelen
1877*5c591343SA. Cody Schuffelen //*** NvReadMaxCount()
1878*5c591343SA. Cody Schuffelen // This function returns the max NV counter value.
1879*5c591343SA. Cody Schuffelen //
1880*5c591343SA. Cody Schuffelen UINT64
NvReadMaxCount(void)1881*5c591343SA. Cody Schuffelen NvReadMaxCount(
1882*5c591343SA. Cody Schuffelen void
1883*5c591343SA. Cody Schuffelen )
1884*5c591343SA. Cody Schuffelen {
1885*5c591343SA. Cody Schuffelen return s_maxCounter;
1886*5c591343SA. Cody Schuffelen }
1887*5c591343SA. Cody Schuffelen
1888*5c591343SA. Cody Schuffelen //*** NvUpdateMaxCount()
1889*5c591343SA. Cody Schuffelen // This function updates the max counter value to NV memory. This is just staging
1890*5c591343SA. Cody Schuffelen // for the actual write that will occur when the NV index memory is modified.
1891*5c591343SA. Cody Schuffelen //
1892*5c591343SA. Cody Schuffelen void
NvUpdateMaxCount(UINT64 count)1893*5c591343SA. Cody Schuffelen NvUpdateMaxCount(
1894*5c591343SA. Cody Schuffelen UINT64 count
1895*5c591343SA. Cody Schuffelen )
1896*5c591343SA. Cody Schuffelen {
1897*5c591343SA. Cody Schuffelen if(count > s_maxCounter)
1898*5c591343SA. Cody Schuffelen s_maxCounter = count;
1899*5c591343SA. Cody Schuffelen }
1900*5c591343SA. Cody Schuffelen
1901*5c591343SA. Cody Schuffelen //*** NvSetMaxCount()
1902*5c591343SA. Cody Schuffelen // This function is used at NV initialization time to set the initial value of
1903*5c591343SA. Cody Schuffelen // the maximum counter.
1904*5c591343SA. Cody Schuffelen void
NvSetMaxCount(UINT64 value)1905*5c591343SA. Cody Schuffelen NvSetMaxCount(
1906*5c591343SA. Cody Schuffelen UINT64 value
1907*5c591343SA. Cody Schuffelen )
1908*5c591343SA. Cody Schuffelen {
1909*5c591343SA. Cody Schuffelen s_maxCounter = value;
1910*5c591343SA. Cody Schuffelen }
1911*5c591343SA. Cody Schuffelen
1912*5c591343SA. Cody Schuffelen //*** NvGetMaxCount()
1913*5c591343SA. Cody Schuffelen // Function to get the NV max counter value from the end-of-list marker
1914*5c591343SA. Cody Schuffelen UINT64
NvGetMaxCount(void)1915*5c591343SA. Cody Schuffelen NvGetMaxCount(
1916*5c591343SA. Cody Schuffelen void
1917*5c591343SA. Cody Schuffelen )
1918*5c591343SA. Cody Schuffelen {
1919*5c591343SA. Cody Schuffelen NV_REF iter = NV_REF_INIT;
1920*5c591343SA. Cody Schuffelen NV_REF currentAddr;
1921*5c591343SA. Cody Schuffelen UINT64 maxCount;
1922*5c591343SA. Cody Schuffelen //
1923*5c591343SA. Cody Schuffelen // Find the end of list marker and initialize the NV Max Counter value.
1924*5c591343SA. Cody Schuffelen while((currentAddr = NvNext(&iter, NULL )) != 0);
1925*5c591343SA. Cody Schuffelen // 'iter' should be pointing at the end of list marker so read in the current
1926*5c591343SA. Cody Schuffelen // value of the s_maxCounter.
1927*5c591343SA. Cody Schuffelen NvRead(&maxCount, iter + sizeof(UINT32), sizeof(maxCount));
1928*5c591343SA. Cody Schuffelen
1929*5c591343SA. Cody Schuffelen return maxCount;
1930*5c591343SA. Cody Schuffelen }
1931