xref: /openbmc/hiomapd/backend.h (revision affbf2ed)
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 <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 
20 enum backend_reset_mode { reset_lpc_flash, reset_lpc_memory };
21 
22 struct backend_ops;
23 
24 struct 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 
39 struct 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);
126 
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);
137 };
138 
139 /* Make this better */
140 static 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 
157 	if (!(master && master->ops && master->ops->init))
158 		return -ENOTSUP;
159 
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 
170 static inline void backend_free(struct backend *backend)
171 {
172 	assert(backend);
173 
174 	if (backend->ops->free)
175 		backend->ops->free(backend);
176 }
177 
178 static 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 
187 static 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 
199 static 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 
209 static 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 
217 static 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 
228 static 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 
236 
237 static 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 
256 struct backend backend_get_mtd(void);
257 int backend_probe_mtd(struct backend *master, const char *path);
258 
259 struct backend backend_get_file(void);
260 int backend_probe_file(struct backend *master, const char *path);
261 
262 /* Avoid dependency on vpnor/mboxd_pnor_partition_table.h */
263 struct vpnor_partition_paths;
264 #ifdef VIRTUAL_PNOR_ENABLED
265 struct backend backend_get_vpnor(void);
266 
267 int backend_probe_vpnor(struct backend *master,
268                         const struct vpnor_partition_paths *paths);
269 #else
270 static inline struct backend backend_get_vpnor(void)
271 {
272 	struct backend be = { 0 };
273 
274 	return be;
275 }
276 
277 static inline int backend_probe_vpnor(struct backend *master,
278 				      const struct vpnor_partition_paths *paths)
279 {
280 	return -ENOTSUP;
281 }
282 #endif
283 
284 #endif /* BACKEND_H */
285