xref: /openbmc/hiomapd/backend.h (revision 68a24c9e)
1 /* 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>
9 #include <errno.h>
10 #include <stdbool.h>
11 #include <stddef.h>
12 #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 
21 enum backend_reset_mode { reset_lpc_flash, reset_lpc_memory };
22 
23 struct backend_ops;
24 
25 struct 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 
40 struct 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);
127 
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);
138 };
139 
140 /* Make this better */
backend_init(struct backend * master,struct backend * with,void * data)141 static 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 
158 	if (!(master && master->ops && master->ops->init))
159 		return -ENOTSUP;
160 
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 
backend_free(struct backend * backend)171 static inline void backend_free(struct backend *backend)
172 {
173 	assert(backend);
174 
175 	if (backend->ops->free)
176 		backend->ops->free(backend);
177 }
178 
backend_copy(struct backend * backend,uint32_t offset,void * mem,uint32_t size)179 static 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 
backend_set_bytemap(struct backend * backend,uint32_t offset,uint32_t count,uint8_t val)188 static 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 
backend_erase(struct backend * backend,uint32_t offset,uint32_t count)200 static 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 
backend_write(struct backend * backend,uint32_t offset,void * buf,uint32_t count)210 static 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 
backend_validate(struct backend * backend,uint32_t offset,uint32_t size,bool ro)218 static 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 
backend_reset(struct backend * backend,void * buf,uint32_t count)229 static 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 
237 
backend_align_offset(struct backend * backend,uint32_t * offset,uint32_t window_size)238 static 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 
257 struct backend backend_get_mtd(void);
258 int backend_probe_mtd(struct backend *master, const char *path);
259 
260 struct backend backend_get_file(void);
261 int backend_probe_file(struct backend *master, const char *path);
262 
263 /* Avoid dependency on vpnor/mboxd_pnor_partition_table.h */
264 struct vpnor_partition_paths;
265 #ifdef VIRTUAL_PNOR_ENABLED
266 struct backend backend_get_vpnor(void);
267 
268 int backend_probe_vpnor(struct backend *master,
269                         const struct vpnor_partition_paths *paths);
270 #else
backend_get_vpnor(void)271 static inline struct backend backend_get_vpnor(void)
272 {
273 	struct backend be = { NULL, NULL, 0, 0, 0 };
274 
275 	return be;
276 }
277 
backend_probe_vpnor(struct backend * master,const struct vpnor_partition_paths * paths)278 static inline int backend_probe_vpnor(struct backend *master __attribute__((unused)),
279 				      const struct vpnor_partition_paths *paths __attribute__((unused)))
280 {
281 	return -ENOTSUP;
282 }
283 #endif
284 
285 #endif /* BACKEND_H */
286