1f1e547c7SEvan Lojewski /* SPDX-License-Identifier: Apache-2.0 */
2f1e547c7SEvan Lojewski /* Copyright (C) 2018 IBM Corp. */
3f1e547c7SEvan Lojewski /* Copyright (C) 2018 Evan Lojewski. */
4f1e547c7SEvan Lojewski
5f1e547c7SEvan Lojewski #ifndef BACKEND_H
6f1e547c7SEvan Lojewski #define BACKEND_H
7f1e547c7SEvan Lojewski
8f1e547c7SEvan Lojewski #include <assert.h>
95320f6e0SAndrew Jeffery #include <errno.h>
10f1e547c7SEvan Lojewski #include <stdbool.h>
11*68a24c9eSPatrick Williams #include <stddef.h>
12f1e547c7SEvan Lojewski #include <stdint.h>
13f1e547c7SEvan Lojewski #include <mtd/mtd-abi.h>
14f1e547c7SEvan Lojewski
15f1e547c7SEvan Lojewski #define FLASH_DIRTY 0x00
16f1e547c7SEvan Lojewski #define FLASH_ERASED 0x01
17f1e547c7SEvan Lojewski
18f1e547c7SEvan Lojewski /* Estimate as to how long (milliseconds) it takes to access a MB from flash */
19f1e547c7SEvan Lojewski #define FLASH_ACCESS_MS_PER_MB 8000
20f1e547c7SEvan Lojewski
21f1e547c7SEvan Lojewski enum backend_reset_mode { reset_lpc_flash, reset_lpc_memory };
22f1e547c7SEvan Lojewski
23f1e547c7SEvan Lojewski struct backend_ops;
24f1e547c7SEvan Lojewski
25f1e547c7SEvan Lojewski struct backend {
26f1e547c7SEvan Lojewski const struct backend_ops *ops;
27f1e547c7SEvan Lojewski
28f1e547c7SEvan Lojewski /* Backend private data */
29f1e547c7SEvan Lojewski void *priv;
30f1e547c7SEvan Lojewski
31f1e547c7SEvan Lojewski /* Flash size from command line (bytes) */
32f1e547c7SEvan Lojewski uint32_t flash_size;
33f1e547c7SEvan Lojewski
34f1e547c7SEvan Lojewski /* Erase size (as a shift) */
35f1e547c7SEvan Lojewski uint32_t erase_size_shift;
36f1e547c7SEvan Lojewski /* Block size (as a shift) */
37f1e547c7SEvan Lojewski uint32_t block_size_shift;
38f1e547c7SEvan Lojewski };
39f1e547c7SEvan Lojewski
40f1e547c7SEvan Lojewski struct backend_ops {
41f1e547c7SEvan Lojewski /*
42f1e547c7SEvan Lojewski * init() - Main initialization function for backing device
43f1e547c7SEvan Lojewski * @context: The backend context pointer
44f1e547c7SEvan Lojewski * @data: Additional backend-implementation-specifc data
45f1e547c7SEvan Lojewski * Return: Zero on success, otherwise negative error
46f1e547c7SEvan Lojewski */
47f1e547c7SEvan Lojewski int (*init)(struct backend *backend, void *data);
48f1e547c7SEvan Lojewski
49f1e547c7SEvan Lojewski /*
50f1e547c7SEvan Lojewski * free() - Main teardown function for backing device
51f1e547c7SEvan Lojewski * @context: The backend context pointer
52f1e547c7SEvan Lojewski */
53f1e547c7SEvan Lojewski void (*free)(struct backend *backend);
54f1e547c7SEvan Lojewski
55f1e547c7SEvan Lojewski /*
56f1e547c7SEvan Lojewski * copy() - Copy data from the flash device into a provided buffer
57f1e547c7SEvan Lojewski * @context: The mbox context pointer
58f1e547c7SEvan Lojewski * @offset: The flash offset to copy from (bytes)
59f1e547c7SEvan Lojewski * @mem: The buffer to copy into (must be of atleast 'size' bytes)
60f1e547c7SEvan Lojewski * @size: The number of bytes to copy
61f1e547c7SEvan Lojewski * Return: Number of bytes copied on success, otherwise negative error
62f1e547c7SEvan Lojewski * code. flash_copy will copy at most 'size' bytes, but it may
63f1e547c7SEvan Lojewski * copy less.
64f1e547c7SEvan Lojewski */
65f1e547c7SEvan Lojewski int64_t (*copy)(struct backend *backend, uint32_t offset, void *mem,
66f1e547c7SEvan Lojewski uint32_t size);
67f1e547c7SEvan Lojewski
68f1e547c7SEvan Lojewski /*
69f1e547c7SEvan Lojewski * set_bytemap() - Set the flash erased bytemap
70f1e547c7SEvan Lojewski * @context: The mbox context pointer
71f1e547c7SEvan Lojewski * @offset: The flash offset to set (bytes)
72f1e547c7SEvan Lojewski * @count: Number of bytes to set
73f1e547c7SEvan Lojewski * @val: Value to set the bytemap to
74f1e547c7SEvan Lojewski *
75f1e547c7SEvan Lojewski * The flash bytemap only tracks the erased status at the erase block level so
76f1e547c7SEvan Lojewski * this will update the erased state for an (or many) erase blocks
77f1e547c7SEvan Lojewski *
78f1e547c7SEvan Lojewski * Return: 0 if success otherwise negative error code
79f1e547c7SEvan Lojewski */
80f1e547c7SEvan Lojewski int (*set_bytemap)(struct backend *backend, uint32_t offset,
81f1e547c7SEvan Lojewski uint32_t count, uint8_t val);
82f1e547c7SEvan Lojewski
83f1e547c7SEvan Lojewski /*
84f1e547c7SEvan Lojewski * erase() - Erase the flash
85f1e547c7SEvan Lojewski * @context: The backend context pointer
86f1e547c7SEvan Lojewski * @offset: The flash offset to erase (bytes)
87f1e547c7SEvan Lojewski * @size: The number of bytes to erase
88f1e547c7SEvan Lojewski *
89f1e547c7SEvan Lojewski * Return: 0 on success otherwise negative error code
90f1e547c7SEvan Lojewski */
91f1e547c7SEvan Lojewski int (*erase)(struct backend *backend, uint32_t offset,
92f1e547c7SEvan Lojewski uint32_t count);
93f1e547c7SEvan Lojewski /*
94f1e547c7SEvan Lojewski * write() - Write the flash from a provided buffer
95f1e547c7SEvan Lojewski * @context: The backend context pointer
96f1e547c7SEvan Lojewski * @offset: The flash offset to write to (bytes)
97f1e547c7SEvan Lojewski * @buf: The buffer to write from (must be of atleast size)
98f1e547c7SEvan Lojewski * @size: The number of bytes to write
99f1e547c7SEvan Lojewski *
100f1e547c7SEvan Lojewski * Return: 0 on success otherwise negative error code
101f1e547c7SEvan Lojewski */
102f1e547c7SEvan Lojewski int (*write)(struct backend *backend, uint32_t offset, void *buf,
103f1e547c7SEvan Lojewski uint32_t count);
104f1e547c7SEvan Lojewski
105f1e547c7SEvan Lojewski /*
106f1e547c7SEvan Lojewski * validate() - Validates a requested window
107f1e547c7SEvan Lojewski * @context: The backend context pointer
108f1e547c7SEvan Lojewski * @offset: The requested flash offset
109f1e547c7SEvan Lojewski * @size: The requested region size
110f1e547c7SEvan Lojewski * @ro: The requested access type: True for read-only, false
111f1e547c7SEvan Lojewski * for read-write
112f1e547c7SEvan Lojewski *
113f1e547c7SEvan Lojewski * Return: 0 on valid otherwise negative error code
114f1e547c7SEvan Lojewski */
115f1e547c7SEvan Lojewski int (*validate)(struct backend *backend,
116f1e547c7SEvan Lojewski uint32_t offset, uint32_t size, bool ro);
117f1e547c7SEvan Lojewski
118f1e547c7SEvan Lojewski /*
119f1e547c7SEvan Lojewski * reset() - Ready the reserved memory for host startup
120f1e547c7SEvan Lojewski * @context: The backend context pointer
121f1e547c7SEvan Lojewski * @buf: The LPC reserved memory pointer
122f1e547c7SEvan Lojewski * @count The size of the LPC reserved memory region
123f1e547c7SEvan Lojewski *
124f1e547c7SEvan Lojewski * Return: 0 on success otherwise negative error code
125f1e547c7SEvan Lojewski */
126f1e547c7SEvan Lojewski int (*reset)(struct backend *backend, void *buf, uint32_t count);
1278cef63e3SAlvin Wang
1288cef63e3SAlvin Wang /*
1298cef63e3SAlvin Wang * align_offset() - Align the offset to avoid overlap
1308cef63e3SAlvin Wang * @context: The backend context pointer
1318cef63e3SAlvin Wang * @offset: The flash offset
1328cef63e3SAlvin Wang * @window_size:The window size
1338cef63e3SAlvin Wang *
1348cef63e3SAlvin Wang * Return: 0 on success otherwise negative error code
1358cef63e3SAlvin Wang */
1368cef63e3SAlvin Wang int (*align_offset)(struct backend *backend, uint32_t *offset,
1378cef63e3SAlvin Wang uint32_t window_size);
138f1e547c7SEvan Lojewski };
139f1e547c7SEvan Lojewski
140f1e547c7SEvan Lojewski /* Make this better */
backend_init(struct backend * master,struct backend * with,void * data)141f1e547c7SEvan Lojewski static inline int backend_init(struct backend *master, struct backend *with,
142f1e547c7SEvan Lojewski void *data)
143f1e547c7SEvan Lojewski {
144f1e547c7SEvan Lojewski int rc;
145f1e547c7SEvan Lojewski
146f1e547c7SEvan Lojewski assert(master);
147f1e547c7SEvan Lojewski
148f1e547c7SEvan Lojewski /* FIXME: A bit hacky? */
149f1e547c7SEvan Lojewski with->flash_size = master->flash_size;
150f1e547c7SEvan Lojewski *master = *with;
151f1e547c7SEvan Lojewski
152f1e547c7SEvan Lojewski #ifndef NDEBUG
153f1e547c7SEvan Lojewski /* Set some poison values to ensure backends init properly */
154f1e547c7SEvan Lojewski master->erase_size_shift = 33;
155f1e547c7SEvan Lojewski master->block_size_shift = 34;
156f1e547c7SEvan Lojewski #endif
157f1e547c7SEvan Lojewski
158affbf2edSAndrew Jeffery if (!(master && master->ops && master->ops->init))
1595320f6e0SAndrew Jeffery return -ENOTSUP;
160f1e547c7SEvan Lojewski
161f1e547c7SEvan Lojewski rc = master->ops->init(master, data);
162f1e547c7SEvan Lojewski if (rc < 0)
163f1e547c7SEvan Lojewski return rc;
164f1e547c7SEvan Lojewski
165f1e547c7SEvan Lojewski assert(master->erase_size_shift < 32);
166f1e547c7SEvan Lojewski assert(master->block_size_shift < 32);
167f1e547c7SEvan Lojewski
168f1e547c7SEvan Lojewski return 0;
169f1e547c7SEvan Lojewski }
170f1e547c7SEvan Lojewski
backend_free(struct backend * backend)171f1e547c7SEvan Lojewski static inline void backend_free(struct backend *backend)
172f1e547c7SEvan Lojewski {
173f1e547c7SEvan Lojewski assert(backend);
174f1e547c7SEvan Lojewski
175f1e547c7SEvan Lojewski if (backend->ops->free)
176f1e547c7SEvan Lojewski backend->ops->free(backend);
177f1e547c7SEvan Lojewski }
178f1e547c7SEvan Lojewski
backend_copy(struct backend * backend,uint32_t offset,void * mem,uint32_t size)179f1e547c7SEvan Lojewski static inline int64_t backend_copy(struct backend *backend,
180f1e547c7SEvan Lojewski uint32_t offset, void *mem, uint32_t size)
181f1e547c7SEvan Lojewski {
182f1e547c7SEvan Lojewski assert(backend);
183f1e547c7SEvan Lojewski assert(backend->ops->copy);
184f1e547c7SEvan Lojewski return backend->ops->copy(backend, offset, mem, size);
185f1e547c7SEvan Lojewski
186f1e547c7SEvan Lojewski }
187f1e547c7SEvan Lojewski
backend_set_bytemap(struct backend * backend,uint32_t offset,uint32_t count,uint8_t val)188f1e547c7SEvan Lojewski static inline int backend_set_bytemap(struct backend *backend,
189f1e547c7SEvan Lojewski uint32_t offset, uint32_t count,
190f1e547c7SEvan Lojewski uint8_t val)
191f1e547c7SEvan Lojewski {
192f1e547c7SEvan Lojewski assert(backend);
193f1e547c7SEvan Lojewski
194f1e547c7SEvan Lojewski if (backend->ops->set_bytemap)
195f1e547c7SEvan Lojewski return backend->ops->set_bytemap(backend, offset, count, val);
196f1e547c7SEvan Lojewski
197f1e547c7SEvan Lojewski return 0;
198f1e547c7SEvan Lojewski }
199f1e547c7SEvan Lojewski
backend_erase(struct backend * backend,uint32_t offset,uint32_t count)200f1e547c7SEvan Lojewski static inline int backend_erase(struct backend *backend, uint32_t offset,
201f1e547c7SEvan Lojewski uint32_t count)
202f1e547c7SEvan Lojewski {
203f1e547c7SEvan Lojewski assert(backend);
204f1e547c7SEvan Lojewski if (backend->ops->erase)
205f1e547c7SEvan Lojewski return backend->ops->erase(backend, offset, count);
206f1e547c7SEvan Lojewski
207f1e547c7SEvan Lojewski return 0;
208f1e547c7SEvan Lojewski }
209f1e547c7SEvan Lojewski
backend_write(struct backend * backend,uint32_t offset,void * buf,uint32_t count)210f1e547c7SEvan Lojewski static inline int backend_write(struct backend *backend, uint32_t offset,
211f1e547c7SEvan Lojewski void *buf, uint32_t count)
212f1e547c7SEvan Lojewski {
213f1e547c7SEvan Lojewski assert(backend);
214f1e547c7SEvan Lojewski assert(backend->ops->write);
215f1e547c7SEvan Lojewski return backend->ops->write(backend, offset, buf, count);
216f1e547c7SEvan Lojewski }
217f1e547c7SEvan Lojewski
backend_validate(struct backend * backend,uint32_t offset,uint32_t size,bool ro)218f1e547c7SEvan Lojewski static inline int backend_validate(struct backend *backend,
219f1e547c7SEvan Lojewski uint32_t offset, uint32_t size, bool ro)
220f1e547c7SEvan Lojewski {
221f1e547c7SEvan Lojewski assert(backend);
222f1e547c7SEvan Lojewski
223f1e547c7SEvan Lojewski if (backend->ops->validate)
224f1e547c7SEvan Lojewski return backend->ops->validate(backend, offset, size, ro);
225f1e547c7SEvan Lojewski
226f1e547c7SEvan Lojewski return 0;
227f1e547c7SEvan Lojewski }
228f1e547c7SEvan Lojewski
backend_reset(struct backend * backend,void * buf,uint32_t count)229f1e547c7SEvan Lojewski static inline int backend_reset(struct backend *backend, void *buf,
230f1e547c7SEvan Lojewski uint32_t count)
231f1e547c7SEvan Lojewski {
232f1e547c7SEvan Lojewski assert(backend);
233f1e547c7SEvan Lojewski assert(backend->ops->reset);
234f1e547c7SEvan Lojewski return backend->ops->reset(backend, buf, count);
235f1e547c7SEvan Lojewski }
236f1e547c7SEvan Lojewski
2378cef63e3SAlvin Wang
backend_align_offset(struct backend * backend,uint32_t * offset,uint32_t window_size)2388cef63e3SAlvin Wang static inline int backend_align_offset(struct backend *backend, uint32_t *offset, uint32_t window_size)
2398cef63e3SAlvin Wang {
2408cef63e3SAlvin Wang assert(backend);
2418cef63e3SAlvin Wang if (backend->ops->align_offset){
2428cef63e3SAlvin Wang return backend->ops->align_offset(backend, offset, window_size);
2438cef63e3SAlvin Wang }else{
2448cef63e3SAlvin Wang /*
2458cef63e3SAlvin Wang * It would be nice to align the offsets which we map to window
2468cef63e3SAlvin Wang * size, this will help prevent overlap which would be an
2478cef63e3SAlvin Wang * inefficient use of our reserved memory area (we would like
2488cef63e3SAlvin Wang * to "cache" as much of the acutal flash as possible in
2498cef63e3SAlvin Wang * memory). If we're protocol V1 however we must ensure the
2508cef63e3SAlvin Wang * offset requested is exactly mapped.
2518cef63e3SAlvin Wang */
2528cef63e3SAlvin Wang *offset &= ~(window_size - 1);
2538cef63e3SAlvin Wang return 0;
2548cef63e3SAlvin Wang }
2558cef63e3SAlvin Wang }
2568cef63e3SAlvin Wang
2575320f6e0SAndrew Jeffery struct backend backend_get_mtd(void);
258f1e547c7SEvan Lojewski int backend_probe_mtd(struct backend *master, const char *path);
2595320f6e0SAndrew Jeffery
2605320f6e0SAndrew Jeffery struct backend backend_get_file(void);
261a042978bSEvan Lojewski int backend_probe_file(struct backend *master, const char *path);
2625320f6e0SAndrew Jeffery
263f1e547c7SEvan Lojewski /* Avoid dependency on vpnor/mboxd_pnor_partition_table.h */
264f1e547c7SEvan Lojewski struct vpnor_partition_paths;
2655320f6e0SAndrew Jeffery #ifdef VIRTUAL_PNOR_ENABLED
2665320f6e0SAndrew Jeffery struct backend backend_get_vpnor(void);
2675320f6e0SAndrew Jeffery
268f1e547c7SEvan Lojewski int backend_probe_vpnor(struct backend *master,
269f1e547c7SEvan Lojewski const struct vpnor_partition_paths *paths);
2705320f6e0SAndrew Jeffery #else
backend_get_vpnor(void)2715320f6e0SAndrew Jeffery static inline struct backend backend_get_vpnor(void)
2725320f6e0SAndrew Jeffery {
273*68a24c9eSPatrick Williams struct backend be = { NULL, NULL, 0, 0, 0 };
2745320f6e0SAndrew Jeffery
2755320f6e0SAndrew Jeffery return be;
2765320f6e0SAndrew Jeffery }
2775320f6e0SAndrew Jeffery
backend_probe_vpnor(struct backend * master,const struct vpnor_partition_paths * paths)278*68a24c9eSPatrick Williams static inline int backend_probe_vpnor(struct backend *master __attribute__((unused)),
279*68a24c9eSPatrick Williams const struct vpnor_partition_paths *paths __attribute__((unused)))
2805320f6e0SAndrew Jeffery {
2815320f6e0SAndrew Jeffery return -ENOTSUP;
2825320f6e0SAndrew Jeffery }
2835320f6e0SAndrew Jeffery #endif
284f1e547c7SEvan Lojewski
285f1e547c7SEvan Lojewski #endif /* BACKEND_H */
286