summaryrefslogtreecommitdiff
path: root/board/cr50/tpm2/NVMem.c
blob: 9ea2c83926d4a2ed32968f1be77bb01b4fa4b0e1 (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
/* Copyright 2015 The ChromiumOS Authors
 * 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 "Platform.h"
#include "PlatformData.h"
#include "TPM_Types.h"
#include "TpmError.h"
#include "assert.h"
#include "ccd_config.h"
#include "ec_comm.h"
#include "nvmem.h"
#include "tpm_nvmem.h"

/* Local state */
static struct {
	BOOL s_NvIsAvailable;
	BOOL s_NV_unrecoverable;
	BOOL s_NV_recoverable;
} local_state  __attribute__((section(".bss.Tpm2_common")));
/*
 * 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)
{
	local_state.s_NV_unrecoverable = unrecoverable;
	local_state.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)
{
	local_state.s_NV_unrecoverable = FALSE;
	local_state.s_NV_recoverable = FALSE;

	/* 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
	 */
	local_state.s_NV_recoverable = nvmem_get_error_state() != 0;
	local_state.s_NV_unrecoverable = local_state.s_NV_recoverable;

	if (local_state.s_NV_unrecoverable)
		return -1;
	return local_state.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)
{

	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 = !local_state.s_NvIsAvailable || nvmem_get_error_state();
	return rv;
}

/*
 * Read a chunk of NV memory
 */
void _plat__NvMemoryRead(unsigned int startOffset,
				    unsigned int size,
				    void *data)
{
	if (_plat__NvOffsetIsVirtual(startOffset)) {
		_plat__NvVirtualMemoryRead(startOffset, size, data);
		return;
	}

	assert(startOffset + size <= NV_MEMORY_SIZE);
	/* Copy the data from the NV image */
	nvmem_read(startOffset, size, data, NVMEM_TPM);
	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)
{
	return (nvmem_is_different(startOffset, size, data, NVMEM_TPM) != 0);
}

/*
 * 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 */
	nvmem_write(startOffset, size, data, NVMEM_TPM);
}

/*
 *      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);
	nvmem_move(sourceOffset, destOffset, size, NVMEM_TPM);
	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)
{
	return nvmem_commit();
}

/*
 * 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)
{
	local_state.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)
{
	local_state.s_NvIsAvailable = FALSE;
	return;
}

void _plat__NvInformIndexDataChanged(unsigned int handle)
{
	if (handle == (HR_NV_INDEX + FWMP_NV_INDEX))
		board_fwmp_update_policies();
	if (handle == (HR_NV_INDEX + KERNEL_NV_INDEX))
		ec_efs_refresh();
}