summaryrefslogtreecommitdiff
path: root/include/new_nvmem.h
blob: 9aa551c7615e7e63e641a12f807e8e04c183aa22 (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
/* Copyright 2019 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.
 */
#ifndef __TPM2_NVMEM_TEST_NEW_NVMEM_H
#define __TPM2_NVMEM_TEST_NEW_NVMEM_H

#include "common.h"
#include "nvmem.h"
#include "nvmem_vars.h"
#include "util.h"

#define NVMEM_NOT_INITIALIZED ((unsigned int)-1)

/*
 * A totally arbitrary byte limit for space occupied by (key, value) pairs in
 * the flash. This is an improvement compared to the legacy case where there
 * were just 272 bytes dedicated to the (key, value) pairs storage.
 */
#define MAX_VAR_TOTAL_SPACE 1000

/*
 * Let's be reasonable: we're unlikely to have keys longer than 40 or so
 * bytes, and leave full 255 bytes for the value. Total data space occupied by
 * a (key, value) pair is not to exceed the value below.
 */
#define MAX_VAR_BODY_SPACE 300

enum nn_object_type {
	NN_OBJ_OLD_COPY = 0,
	NN_OBJ_TUPLE = 1,
	NN_OBJ_TPM_RESERVED = 2,
	NN_OBJ_TPM_EVICTABLE = 3,
	NN_OBJ_TRANSACTION_DEL = 4,
	NN_OBJ_ESCAPE = 5,
	NN_OBJ_ERASED = 7,
};

/*
 * Structure placed at the base of each flash page used for NVMEM storage.
 *
 * page_number: allows to arrange pages in order they were added
 *
 * data_offset: the offset of the first element in the page (space above
 *              page header and below data_offset could be taken by the
 *              'tail' of the object stored on the previous page).
 *
 * page_hash:   is used to verify page header integrity
 */
struct nn_page_header {
	unsigned int page_number : 21;
	unsigned int data_offset : 11;
	uint32_t page_hash;
} __packed;

/*
 * Index of the 'virtual' last reserved object. RAM index space and max
 * counter objects stored at fixed location in the NVMEM cache are considered
 * reserved objects by this NVMEM flash layer.
 */
#define NV_VIRTUAL_RESERVE_LAST (NV_RESERVE_LAST + 2)

/*
 * Container header for all blobs stored in flash.
 *
 * container_type: type of object stored in the container. MAKE SURE THIS
 *                 FIELD TYPE IS THE FIRST FIELD IN THIS STRUCTURE, it is
 *                 supposed to be in the first word of the container so that
 *                 the type can be erased when object is deleted.
 *
 * container_type_copy: immutable copy of the container_type field, used to
 *                      verify contents of deleted objects.
 *
 * encrypted: set to 1 if contents are encrypted.
 *
 * size: size of the payload, 12 bits allocated, 11 bits would be enough for
 *       this use case.
 *
 * generation: a free running counter, used to compare ages of two containers
 *
 * container_hash: hash of the ENTIRE container, both header and body
 *                 included. This field is set to zero before hash is calculated
 */
struct nn_container {
	unsigned int container_type : 3;
	unsigned int container_type_copy : 3;
	unsigned int encrypted : 1;
	unsigned int size : 11;
	unsigned int generation : 2;
	unsigned int container_hash : 12;
} __packed;

/*
 * A structure to keep context of accessing to a page, page header and offset
 * define where the next access would happen.
 */
struct page_tracker {
	const struct nn_page_header *ph;
	uint16_t data_offset;
};

/*
 * Helper structure to keep track of accesses to the flash storage.
 *
 * mt:  main tracker for read or write accesses.
 *
 * ct:  keeps track of container fetches, as the location of containers has
 *      special significance: it is both part of the seed used when
 *      encrypting/decryping container contents, and also is necessary to
 *      unwind reading of the container header when the end of storage is
 *      reached and a header of all 0xff is read.
 *
 * dt:  keeps track of delimiters which is important when assessing flash
 *      contents integrity. If during startup the last item in flash is not a
 *      delimiter, this is an indication of a failed transaction, all data
 *      after the previous delimiter needs to be discarded.
 *
 * list_index; index of the current page in the list of pages, useful when
 *             sequential reading and need to get to the next page in the
 *             list.
 */

struct access_tracker {
	struct page_tracker mt; /* Main tracker. */
	struct page_tracker ct; /* Container tracker. */
	struct page_tracker dt; /* Delimiter tracker.*/
	uint8_t list_index;
};

/*
 * New nvmem interface functions, each of them could be blocking because each
 * of them acquires nvmem flash protectioin mutex before proceeding.
 */
enum ec_error_list new_nvmem_init(void);
enum ec_error_list new_nvmem_migrate(unsigned int nvmem_act_partition);
enum ec_error_list new_nvmem_save(void);

/*
 * nvmem_erase_tpm_data_selective
 *
 * Delete from NVMEM TPM NVMEM objects listed in the zero terminated array of
 * indices. If the pointer to the array is NULL - delete all TPM objects.
 *
 * Once deletion is completed, fill up the current top page with erased
 * objects, then compact the flash storage. This will ensure that the NVMEM
 * does not contain erased instances of deleted objects.
 */
int nvmem_erase_tpm_data_selective(const uint32_t *objs_to_erase);

/* Erase all TMP NVMEM objects. */
static inline int nvmem_erase_tpm_data(void)
{
	return nvmem_erase_tpm_data_selective(NULL);
}

#if defined(TEST_BUILD) && !defined(TEST_FUZZ)
#define NVMEM_TEST_BUILD
enum ec_error_list browse_flash_contents(int);
enum ec_error_list compact_nvmem(void);
extern struct access_tracker master_at;
extern uint16_t total_var_space;
int is_uninitialized(const void *p, size_t size);
size_t init_object_offsets(uint16_t *offsets, size_t count);
struct nn_page_header *list_element_to_ph(size_t el);
void *evictable_offs_to_addr(uint16_t offset);
enum ec_error_list get_next_object(struct access_tracker *at,
				   struct nn_container *ch,
				   int include_deleted);
#endif


#endif /* ! __TPM2_NVMEM_TEST_NEW_NVMEM_H */