blob: fadc94b098f63a4c36c9684faa7a6578158dd2c9 [file] [log] [blame]
Evan Lojewskif1e547c2019-03-14 14:34:33 +10301/* SPDX-License-Identifier: Apache-2.0 */
2/* Copyright (C) 2018 IBM Corp. */
3/* Copyright (C) 2018 Evan Lojewski. */
4
5#ifndef BACKEND_H
6#define BACKEND_H
7
8#include <assert.h>
Andrew Jeffery5320f6e2019-03-15 12:40:41 +10309#include <errno.h>
Evan Lojewskif1e547c2019-03-14 14:34:33 +103010#include <stdbool.h>
11#include <stdint.h>
12#include <mtd/mtd-abi.h>
13
14#define FLASH_DIRTY 0x00
15#define FLASH_ERASED 0x01
16
17/* Estimate as to how long (milliseconds) it takes to access a MB from flash */
18#define FLASH_ACCESS_MS_PER_MB 8000
19
Evan Lojewskif1e547c2019-03-14 14:34:33 +103020enum backend_reset_mode { reset_lpc_flash, reset_lpc_memory };
21
22struct backend_ops;
23
24struct backend {
25 const struct backend_ops *ops;
26
27 /* Backend private data */
28 void *priv;
29
30 /* Flash size from command line (bytes) */
31 uint32_t flash_size;
32
33 /* Erase size (as a shift) */
34 uint32_t erase_size_shift;
35 /* Block size (as a shift) */
36 uint32_t block_size_shift;
37};
38
39struct backend_ops {
40 /*
41 * init() - Main initialization function for backing device
42 * @context: The backend context pointer
43 * @data: Additional backend-implementation-specifc data
44 * Return: Zero on success, otherwise negative error
45 */
46 int (*init)(struct backend *backend, void *data);
47
48 /*
49 * free() - Main teardown function for backing device
50 * @context: The backend context pointer
51 */
52 void (*free)(struct backend *backend);
53
54 /*
55 * copy() - Copy data from the flash device into a provided buffer
56 * @context: The mbox context pointer
57 * @offset: The flash offset to copy from (bytes)
58 * @mem: The buffer to copy into (must be of atleast 'size' bytes)
59 * @size: The number of bytes to copy
60 * Return: Number of bytes copied on success, otherwise negative error
61 * code. flash_copy will copy at most 'size' bytes, but it may
62 * copy less.
63 */
64 int64_t (*copy)(struct backend *backend, uint32_t offset, void *mem,
65 uint32_t size);
66
67 /*
68 * set_bytemap() - Set the flash erased bytemap
69 * @context: The mbox context pointer
70 * @offset: The flash offset to set (bytes)
71 * @count: Number of bytes to set
72 * @val: Value to set the bytemap to
73 *
74 * The flash bytemap only tracks the erased status at the erase block level so
75 * this will update the erased state for an (or many) erase blocks
76 *
77 * Return: 0 if success otherwise negative error code
78 */
79 int (*set_bytemap)(struct backend *backend, uint32_t offset,
80 uint32_t count, uint8_t val);
81
82 /*
83 * erase() - Erase the flash
84 * @context: The backend context pointer
85 * @offset: The flash offset to erase (bytes)
86 * @size: The number of bytes to erase
87 *
88 * Return: 0 on success otherwise negative error code
89 */
90 int (*erase)(struct backend *backend, uint32_t offset,
91 uint32_t count);
92 /*
93 * write() - Write the flash from a provided buffer
94 * @context: The backend context pointer
95 * @offset: The flash offset to write to (bytes)
96 * @buf: The buffer to write from (must be of atleast size)
97 * @size: The number of bytes to write
98 *
99 * Return: 0 on success otherwise negative error code
100 */
101 int (*write)(struct backend *backend, uint32_t offset, void *buf,
102 uint32_t count);
103
104 /*
105 * validate() - Validates a requested window
106 * @context: The backend context pointer
107 * @offset: The requested flash offset
108 * @size: The requested region size
109 * @ro: The requested access type: True for read-only, false
110 * for read-write
111 *
112 * Return: 0 on valid otherwise negative error code
113 */
114 int (*validate)(struct backend *backend,
115 uint32_t offset, uint32_t size, bool ro);
116
117 /*
118 * reset() - Ready the reserved memory for host startup
119 * @context: The backend context pointer
120 * @buf: The LPC reserved memory pointer
121 * @count The size of the LPC reserved memory region
122 *
123 * Return: 0 on success otherwise negative error code
124 */
125 int (*reset)(struct backend *backend, void *buf, uint32_t count);
Alvin Wang8cef63e2019-10-15 23:23:38 +0800126
127 /*
128 * align_offset() - Align the offset to avoid overlap
129 * @context: The backend context pointer
130 * @offset: The flash offset
131 * @window_size:The window size
132 *
133 * Return: 0 on success otherwise negative error code
134 */
135 int (*align_offset)(struct backend *backend, uint32_t *offset,
136 uint32_t window_size);
Evan Lojewskif1e547c2019-03-14 14:34:33 +1030137};
138
139/* Make this better */
140static inline int backend_init(struct backend *master, struct backend *with,
141 void *data)
142{
143 int rc;
144
145 assert(master);
146
147 /* FIXME: A bit hacky? */
148 with->flash_size = master->flash_size;
149 *master = *with;
150
151#ifndef NDEBUG
152 /* Set some poison values to ensure backends init properly */
153 master->erase_size_shift = 33;
154 master->block_size_shift = 34;
155#endif
156
Andrew Jeffery5320f6e2019-03-15 12:40:41 +1030157 if (!master->ops->init)
158 return -ENOTSUP;
Evan Lojewskif1e547c2019-03-14 14:34:33 +1030159
160 rc = master->ops->init(master, data);
161 if (rc < 0)
162 return rc;
163
164 assert(master->erase_size_shift < 32);
165 assert(master->block_size_shift < 32);
166
167 return 0;
168}
169
170static inline void backend_free(struct backend *backend)
171{
172 assert(backend);
173
174 if (backend->ops->free)
175 backend->ops->free(backend);
176}
177
178static inline int64_t backend_copy(struct backend *backend,
179 uint32_t offset, void *mem, uint32_t size)
180{
181 assert(backend);
182 assert(backend->ops->copy);
183 return backend->ops->copy(backend, offset, mem, size);
184
185}
186
187static inline int backend_set_bytemap(struct backend *backend,
188 uint32_t offset, uint32_t count,
189 uint8_t val)
190{
191 assert(backend);
192
193 if (backend->ops->set_bytemap)
194 return backend->ops->set_bytemap(backend, offset, count, val);
195
196 return 0;
197}
198
199static inline int backend_erase(struct backend *backend, uint32_t offset,
200 uint32_t count)
201{
202 assert(backend);
203 if (backend->ops->erase)
204 return backend->ops->erase(backend, offset, count);
205
206 return 0;
207}
208
209static inline int backend_write(struct backend *backend, uint32_t offset,
210 void *buf, uint32_t count)
211{
212 assert(backend);
213 assert(backend->ops->write);
214 return backend->ops->write(backend, offset, buf, count);
215}
216
217static inline int backend_validate(struct backend *backend,
218 uint32_t offset, uint32_t size, bool ro)
219{
220 assert(backend);
221
222 if (backend->ops->validate)
223 return backend->ops->validate(backend, offset, size, ro);
224
225 return 0;
226}
227
228static inline int backend_reset(struct backend *backend, void *buf,
229 uint32_t count)
230{
231 assert(backend);
232 assert(backend->ops->reset);
233 return backend->ops->reset(backend, buf, count);
234}
235
Alvin Wang8cef63e2019-10-15 23:23:38 +0800236
237static inline int backend_align_offset(struct backend *backend, uint32_t *offset, uint32_t window_size)
238{
239 assert(backend);
240 if (backend->ops->align_offset){
241 return backend->ops->align_offset(backend, offset, window_size);
242 }else{
243 /*
244 * It would be nice to align the offsets which we map to window
245 * size, this will help prevent overlap which would be an
246 * inefficient use of our reserved memory area (we would like
247 * to "cache" as much of the acutal flash as possible in
248 * memory). If we're protocol V1 however we must ensure the
249 * offset requested is exactly mapped.
250 */
251 *offset &= ~(window_size - 1);
252 return 0;
253 }
254}
255
Andrew Jeffery5320f6e2019-03-15 12:40:41 +1030256struct backend backend_get_mtd(void);
Evan Lojewskif1e547c2019-03-14 14:34:33 +1030257int backend_probe_mtd(struct backend *master, const char *path);
Andrew Jeffery5320f6e2019-03-15 12:40:41 +1030258
259struct backend backend_get_file(void);
Evan Lojewskia0429782019-03-13 15:25:44 +1030260int backend_probe_file(struct backend *master, const char *path);
Andrew Jeffery5320f6e2019-03-15 12:40:41 +1030261
Evan Lojewskif1e547c2019-03-14 14:34:33 +1030262/* Avoid dependency on vpnor/mboxd_pnor_partition_table.h */
263struct vpnor_partition_paths;
Andrew Jeffery5320f6e2019-03-15 12:40:41 +1030264#ifdef VIRTUAL_PNOR_ENABLED
265struct backend backend_get_vpnor(void);
266
Evan Lojewskif1e547c2019-03-14 14:34:33 +1030267int backend_probe_vpnor(struct backend *master,
268 const struct vpnor_partition_paths *paths);
Andrew Jeffery5320f6e2019-03-15 12:40:41 +1030269#else
270static inline struct backend backend_get_vpnor(void)
271{
272 struct backend be = { 0 };
273
274 return be;
275}
276
277static inline int backend_probe_vpnor(struct backend *master,
278 const struct vpnor_partition_paths *paths)
279{
280 return -ENOTSUP;
281}
282#endif
Evan Lojewskif1e547c2019-03-14 14:34:33 +1030283
284#endif /* BACKEND_H */