summaryrefslogtreecommitdiffstats
path: root/backend.h
blob: f7b56b4eab9ae6a1ec5c1cf563f77c0db6157fa6 (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
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
/* SPDX-License-Identifier: Apache-2.0 */
/* Copyright (C) 2018 IBM Corp. */
/* Copyright (C) 2018 Evan Lojewski. */

#ifndef BACKEND_H
#define BACKEND_H

#include <assert.h>
#include <errno.h>
#include <stdbool.h>
#include <stdint.h>
#include <mtd/mtd-abi.h>

#define FLASH_DIRTY	0x00
#define FLASH_ERASED	0x01

/* Estimate as to how long (milliseconds) it takes to access a MB from flash */
#define FLASH_ACCESS_MS_PER_MB		8000

enum backend_reset_mode { reset_lpc_flash, reset_lpc_memory };

struct backend_ops;

struct backend {
	const struct backend_ops *ops;

	/* Backend private data */
	void *priv;

	/* Flash size from command line (bytes) */
	uint32_t flash_size;

	/* Erase size (as a shift) */
	uint32_t erase_size_shift;
	/* Block size (as a shift) */
	uint32_t block_size_shift;
};

struct backend_ops {
	/*
	 * init() - Main initialization function for backing device
	 * @context:	The backend context pointer
	 * @data:	Additional backend-implementation-specifc data
	 * Return:	Zero on success, otherwise negative error
	 */
	int 	(*init)(struct backend *backend, void *data);

	/*
	 * free() - Main teardown function for backing device
	 * @context:	The backend context pointer
	 */
	void 	(*free)(struct backend *backend);

	/*
	 * copy() - Copy data from the flash device into a provided buffer
	 * @context:	The mbox context pointer
	 * @offset:	The flash offset to copy from (bytes)
	 * @mem:	The buffer to copy into (must be of atleast 'size' bytes)
	 * @size:	The number of bytes to copy
	 * Return:	Number of bytes copied on success, otherwise negative error
	 *		code. flash_copy will copy at most 'size' bytes, but it may
	 *		copy less.
	 */
	int64_t (*copy)(struct backend *backend, uint32_t offset, void *mem,
			uint32_t size);

	/*
	 * set_bytemap() - Set the flash erased bytemap
	 * @context:	The mbox context pointer
	 * @offset:	The flash offset to set (bytes)
	 * @count:	Number of bytes to set
	 * @val:	Value to set the bytemap to
	 *
	 * The flash bytemap only tracks the erased status at the erase block level so
	 * this will update the erased state for an (or many) erase blocks
	 *
	 * Return:	0 if success otherwise negative error code
	 */
	 int 	(*set_bytemap)(struct backend *backend, uint32_t offset,
			       uint32_t count, uint8_t val);

	/*
	 * erase() - Erase the flash
	 * @context:	The backend context pointer
	 * @offset:	The flash offset to erase (bytes)
	 * @size:	The number of bytes to erase
	 *
	 * Return:	0 on success otherwise negative error code
	 */
	int 	(*erase)(struct backend *backend, uint32_t offset,
			 uint32_t count);
	/*
	 * write() - Write the flash from a provided buffer
	 * @context:	The backend context pointer
	 * @offset:	The flash offset to write to (bytes)
	 * @buf:	The buffer to write from (must be of atleast size)
	 * @size:	The number of bytes to write
	 *
	 * Return:	0 on success otherwise negative error code
	 */
	int 	(*write)(struct backend *backend, uint32_t offset, void *buf,
			 uint32_t count);

	/*
	 * validate() - Validates a requested window
	 * @context:	The backend context pointer
	 * @offset:	The requested flash offset
	 * @size:	The requested region size
	 * @ro:		The requested access type: True for read-only, false
	 *		for read-write
	 *
	 * Return:	0 on valid otherwise negative error code
	 */
	int 	(*validate)(struct backend *backend,
			    uint32_t offset, uint32_t size, bool ro);

	/*
	 * reset() - Ready the reserved memory for host startup
	 * @context:    The backend context pointer
	 * @buf:	The LPC reserved memory pointer
	 * @count	The size of the LPC reserved memory region
	 *
	 * Return:      0 on success otherwise negative error code
	 */
	int	(*reset)(struct backend *backend, void *buf, uint32_t count);
};

/* Make this better */
static inline int backend_init(struct backend *master, struct backend *with,
			       void *data)
{
	int rc;

	assert(master);

	/* FIXME: A bit hacky? */
	with->flash_size = master->flash_size;
	*master = *with;

#ifndef NDEBUG
	/* Set some poison values to ensure backends init properly */
	master->erase_size_shift = 33;
	master->block_size_shift = 34;
#endif

	if (!master->ops->init)
		return -ENOTSUP;

	rc = master->ops->init(master, data);
	if (rc < 0)
		return rc;

	assert(master->erase_size_shift < 32);
	assert(master->block_size_shift < 32);

	return 0;
}

static inline void backend_free(struct backend *backend)
{
	assert(backend);

	if (backend->ops->free)
		backend->ops->free(backend);
}

static inline int64_t backend_copy(struct backend *backend,
				   uint32_t offset, void *mem, uint32_t size)
{
	assert(backend);
	assert(backend->ops->copy);
	return backend->ops->copy(backend, offset, mem, size);

}

static inline int backend_set_bytemap(struct backend *backend,
				      uint32_t offset, uint32_t count,
				      uint8_t val)
{
	assert(backend);

	if (backend->ops->set_bytemap)
		return backend->ops->set_bytemap(backend, offset, count, val);

	return 0;
}

static inline int backend_erase(struct backend *backend, uint32_t offset,
				uint32_t count)
{
	assert(backend);
	if (backend->ops->erase)
		return backend->ops->erase(backend, offset, count);

	return 0;
}

static inline int backend_write(struct backend *backend, uint32_t offset,
				void *buf, uint32_t count)
{
	assert(backend);
	assert(backend->ops->write);
	return backend->ops->write(backend, offset, buf, count);
}

static inline int backend_validate(struct backend *backend,
				   uint32_t offset, uint32_t size, bool ro)
{
	assert(backend);

	if (backend->ops->validate)
		return backend->ops->validate(backend, offset, size, ro);

	return 0;
}

static inline int backend_reset(struct backend *backend, void *buf,
				uint32_t count)
{
	assert(backend);
	assert(backend->ops->reset);
	return backend->ops->reset(backend, buf, count);
}

struct backend backend_get_mtd(void);
int backend_probe_mtd(struct backend *master, const char *path);

struct backend backend_get_file(void);
int backend_probe_file(struct backend *master, const char *path);

/* Avoid dependency on vpnor/mboxd_pnor_partition_table.h */
struct vpnor_partition_paths;
#ifdef VIRTUAL_PNOR_ENABLED
struct backend backend_get_vpnor(void);

int backend_probe_vpnor(struct backend *master,
                        const struct vpnor_partition_paths *paths);
#else
static inline struct backend backend_get_vpnor(void)
{
	struct backend be = { 0 };

	return be;
}

static inline int backend_probe_vpnor(struct backend *master,
				      const struct vpnor_partition_paths *paths)
{
	return -ENOTSUP;
}
#endif

#endif /* BACKEND_H */
OpenPOWER on IntegriCloud