xref: /openbmc/hiomapd/backend.h (revision 68a24c9ea5ce11c87fab22a3f4648c7d88c98fee)
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