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