blob: 740851f3f8e65aed983e5ff0227e1c4bf1248d41 [file] [log] [blame]
Vadim Bendebury56797522015-05-20 10:32:25 -07001// This file was extracted from the TCG Published
2// Trusted Platform Module Library
3// Part 4: Supporting Routines
4// Family "2.0"
5// Level 00 Revision 01.16
6// October 30, 2014
7
8#include <memory.h>
Vadim Bendebury081c59c2015-05-31 16:17:39 -07009#include <stdio.h>
Vadim Bendebury56797522015-05-20 10:32:25 -070010#include <string.h>
Vadim Bendebury081c59c2015-05-31 16:17:39 -070011
Vadim Bendebury56797522015-05-20 10:32:25 -070012#include "PlatformData.h"
13#include "TpmError.h"
14#include "assert.h"
Bill Richardson1b1d8292015-09-01 17:21:10 -070015
16#ifndef EMBEDDED_MODE
17#define FILE_BACKED_NV
18#endif
19
20#if defined FILE_BACKED_NV
21static FILE* s_NVFile;
22#endif
23static unsigned char s_NV[NV_MEMORY_SIZE];
24static BOOL s_NvIsAvailable;
25static BOOL s_NV_unrecoverable;
26static BOOL s_NV_recoverable;
Vadim Bendebury56797522015-05-20 10:32:25 -070027//
28//
29// Functions
30//
31// _plat__NvErrors()
32//
33// This function is used by the simulator to set the error flags in the NV subsystem to simulate an error in the
34// NV loading process
35//
36LIB_EXPORT void
37_plat__NvErrors(
38 BOOL recoverable,
39 BOOL unrecoverable
40 )
41{
42 s_NV_unrecoverable = unrecoverable;
43 s_NV_recoverable = recoverable;
44}
45//
46//
47// _plat__NVEnable()
48//
49// Enable NV memory.
50// This version just pulls in data from a file. In a real TPM, with NV on chip, this function would verify the
51// integrity of the saved context. If the NV memory was not on chip but was in something like RPMB, the NV
52// state would be read in, decrypted and integrity checked.
53// The recovery from an integrity failure depends on where the error occurred. It it was in the state that is
54// discarded by TPM Reset, then the error is recoverable if the TPM is reset. Otherwise, the TPM must go
55// into failure mode.
56//
57// Return Value Meaning
58//
59// 0 if success
60// >0 if receive recoverable error
61// <0 if unrecoverable error
62//
63LIB_EXPORT int
64_plat__NVEnable(
65 void *platParameter // IN: platform specific parameter
66 )
67{
Vadim Bendebury56797522015-05-20 10:32:25 -070068 // Start assuming everything is OK
69 s_NV_unrecoverable = FALSE;
70 s_NV_recoverable = FALSE;
71#ifdef FILE_BACKED_NV
72 if(s_NVFile != NULL) return 0;
73 // Try to open an exist NVChip file for read/write
Vadim Bendebury081c59c2015-05-31 16:17:39 -070074 s_NVFile = fopen("NVChip", "r+b");
Vadim Bendebury56797522015-05-20 10:32:25 -070075 if(NULL != s_NVFile)
76 {
77 // See if the NVChip file is empty
78 fseek(s_NVFile, 0, SEEK_END);
79 if(0 == ftell(s_NVFile))
80 s_NVFile = NULL;
81 }
82 if(s_NVFile == NULL)
83 {
84 // Initialize all the byte in the new file to 0
85 memset(s_NV, 0, NV_MEMORY_SIZE);
86 // If NVChip file does not exist, try to create it for read/write
Vadim Bendebury081c59c2015-05-31 16:17:39 -070087 s_NVFile = fopen("NVChip", "w+b");
Vadim Bendebury56797522015-05-20 10:32:25 -070088 // Start initialize at the end of new file
89 fseek(s_NVFile, 0, SEEK_END);
90 // Write 0s to NVChip file
91 fwrite(s_NV, 1, NV_MEMORY_SIZE, s_NVFile);
92 }
93 else
94 {
95 // If NVChip file exist, assume the size is correct
96 fseek(s_NVFile, 0, SEEK_END);
97 assert(ftell(s_NVFile) == NV_MEMORY_SIZE);
98 // read NV file data to memory
99 fseek(s_NVFile, 0, SEEK_SET);
Bill Richardson2faf06e2015-08-24 16:45:48 -0700100 assert(1 == fread(s_NV, NV_MEMORY_SIZE, 1, s_NVFile));
Vadim Bendebury56797522015-05-20 10:32:25 -0700101 }
102#endif
103 // NV contents have been read and the error checks have been performed. For
104 // simulation purposes, use the signaling interface to indicate if an error is
105 // to be simulated and the type of the error.
106 if(s_NV_unrecoverable)
107 return -1;
108 return s_NV_recoverable;
109}
110//
111//
112// _plat__NVDisable()
113//
114// Disable NV memory
115//
116LIB_EXPORT void
117_plat__NVDisable(
118 void
119 )
120{
121#ifdef FILE_BACKED_NV
122 assert(s_NVFile != NULL);
123 // Close NV file
124 fclose(s_NVFile);
125 // Set file handle to NULL
126//
127 s_NVFile = NULL;
128#endif
129 return;
130}
131//
132//
133// _plat__IsNvAvailable()
134//
135// Check if NV is available
136//
137// Return Value Meaning
138//
139// 0 NV is available
140// 1 NV is not available due to write failure
141// 2 NV is not available due to rate limit
142//
143LIB_EXPORT int
144_plat__IsNvAvailable(
145 void
146 )
147{
148 // NV is not available if the TPM is in failure mode
149 if(!s_NvIsAvailable)
150 return 1;
151#ifdef FILE_BACKED_NV
152 if(s_NVFile == NULL)
153 return 1;
154#endif
155 return 0;
156}
157//
158//
159// _plat__NvMemoryRead()
160//
161// Function: Read a chunk of NV memory
162//
163LIB_EXPORT void
164_plat__NvMemoryRead(
165 unsigned int startOffset, // IN: read start
166 unsigned int size, // IN: size of bytes to read
167 void *data // OUT: data buffer
168 )
169{
170 assert(startOffset + size <= NV_MEMORY_SIZE);
171 // Copy data from RAM
172 memcpy(data, &s_NV[startOffset], size);
173 return;
174}
175//
176//
177// _plat__NvIsDifferent()
178//
179// This function checks to see if the NV is different from the test value. This is so that NV will not be written if
180// it has not changed.
181//
182//
183//
184//
185// Return Value Meaning
186//
187// TRUE the NV location is different from the test value
188// FALSE the NV location is the same as the test value
189//
190LIB_EXPORT BOOL
191_plat__NvIsDifferent(
192 unsigned int startOffset, // IN: read start
193 unsigned int size, // IN: size of bytes to read
194 void *data // IN: data buffer
195 )
196{
197 return (memcmp(&s_NV[startOffset], data, size) != 0);
198}
199//
200//
201// _plat__NvMemoryWrite()
202//
203// This function is used to update NV memory. The write is to a memory copy of NV. At the end of the
204// current command, any changes are written to the actual NV memory.
205//
206LIB_EXPORT void
207_plat__NvMemoryWrite(
208 unsigned int startOffset, // IN: write start
209 unsigned int size, // IN: size of bytes to write
210 void *data // OUT: data buffer
211 )
212{
213 assert(startOffset + size <= NV_MEMORY_SIZE);
214 // Copy the data to the NV image
215 memcpy(&s_NV[startOffset], data, size);
216}
217//
218//
219// _plat__NvMemoryMove()
220//
221// Function: Move a chunk of NV memory from source to destination This function should ensure that if
222// there overlap, the original data is copied before it is written
223//
224LIB_EXPORT void
225_plat__NvMemoryMove(
226 unsigned int sourceOffset, // IN: source offset
227 unsigned int destOffset, // IN: destination offset
228 unsigned int size // IN: size of data being moved
229 )
230{
231 assert(sourceOffset + size <= NV_MEMORY_SIZE);
232 assert(destOffset + size <= NV_MEMORY_SIZE);
233 // Move data in RAM
234 memmove(&s_NV[destOffset], &s_NV[sourceOffset], size);
235 return;
236}
237//
238//
239// _plat__NvCommit()
240//
241// Update NV chip
242//
243//
244//
245// Return Value Meaning
246//
247// 0 NV write success
248// non-0 NV write fail
249//
250LIB_EXPORT int
251_plat__NvCommit(
252 void
253 )
254{
255#ifdef FILE_BACKED_NV
256 // If NV file is not available, return failure
257 if(s_NVFile == NULL)
258 return 1;
259 // Write RAM data to NV
260 fseek(s_NVFile, 0, SEEK_SET);
261 fwrite(s_NV, 1, NV_MEMORY_SIZE, s_NVFile);
262 return 0;
263#else
264 return 0;
265#endif
266}
267//
268//
269// _plat__SetNvAvail()
270//
271// Set the current NV state to available. This function is for testing purpose only. It is not part of the
272// platform NV logic
273//
274LIB_EXPORT void
275_plat__SetNvAvail(
276 void
277 )
278{
279 s_NvIsAvailable = TRUE;
280 return;
281}
282//
283//
284// _plat__ClearNvAvail()
285//
286// Set the current NV state to unavailable. This function is for testing purpose only. It is not part of the
287// platform NV logic
288//
289LIB_EXPORT void
290_plat__ClearNvAvail(
291 void
292 )
293{
294 s_NvIsAvailable = FALSE;
295 return;
296}