summaryrefslogtreecommitdiff
path: root/board/cr50/tpm2/NVMem.c
blob: 695debe26c90c97f6f522e80046442121a05182b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
/* Copyright 2015 The Chromium OS Authors. All rights reserved.
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 *
 * The function prototypes were extracted from the TCG Published
 * Trusted Platform Module Library
 * Part 4: Supporting Routines
 * Family "2.0"
 * Level 00 Revision 01.16
 * October 30, 2014
 */

#include <string.h>

#include "PlatformData.h"
#include "TpmError.h"
#include "assert.h"
#include "nvmem.h"

/* Local state */
#ifndef CONFIG_FLASH_NVMEM
static unsigned char s_NV[NV_MEMORY_SIZE];
#endif
static BOOL s_NvIsAvailable;
static BOOL s_NV_unrecoverable;
static BOOL s_NV_recoverable;

/*
 * This function is used by the simulator to set the error flags in the NV
 * subsystem to simulate an error in the NV loading process.
 */
void _plat__NvErrors(BOOL recoverable, BOOL unrecoverable)
{
	s_NV_unrecoverable = unrecoverable;
	s_NV_recoverable = recoverable;
}

/*
 * This function should retrieve and verify the integrity of the saved context.
 * On success, the NV content has been copied into local RAM for fast access.
 *
 * The recovery from an integrity failure depends on where the error occurred.
 * It it was in the state that is discarded by TPM Reset, then the error is
 * recoverable if the TPM is reset. Otherwise, the TPM must go into failure
 * mode.
 *
 *     Return Value                      Meaning
 *
 *     0                                 if success
 *     >0                                if receive recoverable error
 *     <0                                if unrecoverable error
 */
int _plat__NVEnable(void *platParameter)
{
	s_NV_unrecoverable = FALSE;
	s_NV_recoverable = FALSE;

#ifdef CONFIG_FLASH_NVMEM
	/* TODO: Need to define what is recoverable and unrecoverable
	 * conditions with regards to NvMem module. For now, the only
	 * requirement is that at Cr50 board initialization time, the
	 * nvmem_init() function either detects a valid partition, or
	 * determines that NvMem is fully erased and configures  a valid
	 * partition. Setting both variables TRUE if NvMem is not available
	 */
	s_NV_recoverable = nvmem_get_error_state() != 0;
	s_NV_unrecoverable = s_NV_recoverable;
#endif
	if (s_NV_unrecoverable)
		return -1;
	return s_NV_recoverable;
}

void _plat__NVDisable(void)
{
	/* nothing yet */
}

/*
 * Check if NV is available
 *
 *      Return Value                      Meaning
 *
 *      0                                 NV is available
 *      1                                 NV not available due to write failure
 *      2                                 NV not available due to rate limit
 */
int _plat__IsNvAvailable(void)
{

#ifdef CONFIG_FLASH_NVMEM
	int rv;
	/*
	 * sNv_IsAvailable is a state variable that can be accesed by the
	 * simmulator to control access to NvMemory. This variable and
	 * the on chip NvMem area must be in the correct state for NvMem
	 * to be in 'NV is available' state.
	 */
	rv = !s_NvIsAvailable || nvmem_get_error_state();
	return rv;
#else
	if (!s_NvIsAvailable)
		return 1;

	return 0;
#endif
}

/*
 * Read a chunk of NV memory
 */
void _plat__NvMemoryRead(unsigned int startOffset,
				    unsigned int size,
				    void *data)
{
	assert(startOffset + size <= NV_MEMORY_SIZE);
	/* Copy the data from the NV image */
#ifdef CONFIG_FLASH_NVMEM
	nvmem_read(startOffset, size, data, NVMEM_TPM);
#else
	memcpy(data, &s_NV[startOffset], size);
#endif
	return;
}

/*
 * This function tests to see if the NV is different from the test value.
 * Returns true if different, false if not.
 */
BOOL
_plat__NvIsDifferent(unsigned int startOffset,
		     unsigned int size,
		     void *data)
{
#ifdef CONFIG_FLASH_NVMEM
	return (nvmem_is_different(startOffset, size, data, NVMEM_TPM) != 0);
#else
	/* Do we need a safe memcmp here? */
	return (memcmp(&s_NV[startOffset], data, size) != 0);
#endif
}

/*
 * This function is used to update NV memory. The write is to a memory copy of
 * NV. At the end of the current command, any changes are written to the actual
 * NV memory.
 */
void _plat__NvMemoryWrite(unsigned int startOffset,
			  unsigned int size,
			  void *data)
{
	assert(startOffset + size <= NV_MEMORY_SIZE);
	/* Copy the data to the NV image */
#ifdef CONFIG_FLASH_NVMEM
	nvmem_write(startOffset, size, data, NVMEM_TPM);
#else
	memcpy(&s_NV[startOffset], data, size);
#endif
}

/*
 *      Function: Move a chunk of NV memory from source to destination,
 *      handling overlap correctly.
 */
void _plat__NvMemoryMove(unsigned int sourceOffset,
				    unsigned int destOffset,
				    unsigned int size)
{
	assert(sourceOffset + size <= NV_MEMORY_SIZE);
	assert(destOffset + size <= NV_MEMORY_SIZE);
#ifdef CONFIG_FLASH_NVMEM
	nvmem_move(sourceOffset, destOffset, size, NVMEM_TPM);
#else
	/* Move data in RAM */
	memmove(&s_NV[destOffset], &s_NV[sourceOffset], size);
#endif
	return;
}

/*
 * Commit the local RAM copy to NV storage.
 *
 *      Return Value                      Meaning
 *
 *      0                                 NV write success
 *      non-0                             NV write fail
 */
int _plat__NvCommit(void)
{
#ifdef CONFIG_FLASH_NVMEM
	return nvmem_commit();
#else
	return 0;
#endif
}

/*
 * Set the current NV state to available. This function is for testing purpose
 * only. It is not part of the platform NV logic
 */
void _plat__SetNvAvail(void)
{
	s_NvIsAvailable = TRUE;
	return;
}

/*
 * Set the current NV state to unavailable. This function is for testing
 * purpose only. It is not part of the platform NV logic
 */
void _plat__ClearNvAvail(void)
{
	s_NvIsAvailable = FALSE;
	return;
}

void wipe_nvram(void)
{
#ifdef CONFIG_FLASH_NVMEM
	nvmem_setup(0);
#else
	memset(s_NV, 0xff, sizeof(s_NV));
#endif
}