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