1 /*
2  * Copyright (c) 2017-2020 Nordic Semiconductor ASA
3  * Copyright (c) 2015 Runtime Inc
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 #ifndef ZEPHYR_INCLUDE_FS_FCB_H_
8 #define ZEPHYR_INCLUDE_FS_FCB_H_
9 
10 /*
11  * Flash circular buffer.
12  */
13 #include <inttypes.h>
14 #include <limits.h>
15 
16 #include <storage/flash_map.h>
17 
18 #include <kernel.h>
19 
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23 
24 /**
25  * @defgroup fcb Flash Circular Buffer (FCB)
26  * @ingroup file_system_storage
27  * @{
28  * @}
29  */
30 
31 /**
32  * @defgroup fcb_data_structures Flash Circular Buffer Data Structures
33  * @ingroup fcb
34  * @{
35  */
36 
37 #define FCB_MAX_LEN	(CHAR_MAX | CHAR_MAX << 7) /**< Max length of element */
38 
39 /**
40  * @brief FCB entry info structure. This data structure describes the element
41  * location in the flash.
42  *
43  * You would use it to figure out what parameters to pass to flash_area_read()
44  * to read element contents. Or to flash_area_write() when adding a new element.
45  * Entry location is pointer to area (within fcb->f_sectors), and offset
46  * within that area.
47  */
48 struct fcb_entry {
49 	struct flash_sector *fe_sector;
50 	/**< Pointer to info about sector where data are placed */
51 
52 	uint32_t fe_elem_off;
53 	/**< Offset from the start of the sector to beginning of element. */
54 
55 	uint32_t fe_data_off;
56 	/**< Offset from the start of the sector to the start of element. */
57 
58 	uint16_t fe_data_len; /**< Size of data area in fcb entry*/
59 };
60 
61 /**
62  * @brief Helper macro for calculating the data offset related to
63  * the fcb flash_area start offset.
64  *
65  * @param entry fcb entry structure
66  */
67 #define FCB_ENTRY_FA_DATA_OFF(entry) (entry.fe_sector->fs_off +\
68 				      entry.fe_data_off)
69 /**
70  * @brief Structure for transferring complete information about FCB entry
71  * location within flash memory.
72  */
73 struct fcb_entry_ctx {
74 	struct fcb_entry loc; /**< FCB entry info */
75 	const struct flash_area *fap;
76 	/**< Flash area where the entry is placed */
77 };
78 
79 /**
80  * @brief FCB instance structure
81  *
82  * The following data structure describes the FCB itself. First part should
83  * be filled in by the user before calling @ref fcb_init. The second part is
84  * used by FCB for its internal bookkeeping.
85  */
86 struct fcb {
87 	/* Caller of fcb_init fills this in */
88 	uint32_t f_magic;
89 	/**< Magic value, should not be 0xFFFFFFFF.
90 	 * It is xored with inversion of f_erase_value and placed in
91 	 * the beginning of FCB flash sector. FCB uses this when determining
92 	 * whether sector contains valid data or not.
93 	 * Giving it value of 0xFFFFFFFF means leaving bytes of the filed
94 	 * in "erased" state.
95 	 */
96 
97 	uint8_t f_version; /**<  Current version number of the data */
98 	uint8_t f_sector_cnt; /**< Number of elements in sector array */
99 	uint8_t f_scratch_cnt;
100 	/**< Number of sectors to keep empty. This can be used if you need
101 	 * to have scratch space for garbage collecting when FCB fills up.
102 	 */
103 
104 	struct flash_sector *f_sectors;
105 	/**< Array of sectors, must be contiguous */
106 
107 	/* Flash circular buffer internal state */
108 	struct k_mutex f_mtx;
109 	/**< Locking for accessing the FCB data, internal state */
110 
111 	struct flash_sector *f_oldest;
112 	/**< Pointer to flash sector containing the oldest data,
113 	 * internal state
114 	 */
115 
116 	struct fcb_entry f_active; /**< internal state */
117 	uint16_t f_active_id;
118 	/**< Flash location where the newest data is, internal state */
119 
120 	uint8_t f_align;
121 	/**< writes to flash have to aligned to this, internal state */
122 
123 	const struct flash_area *fap;
124 	/**< Flash area used by the fcb instance, , internal state.
125 	 * This can be transfer to FCB user
126 	 */
127 
128 	uint8_t f_erase_value;
129 	/**< The value flash takes when it is erased. This is read from
130 	 * flash parameters and initialized upon call to fcb_init.
131 	 */
132 };
133 
134 /**
135  * @}
136  */
137 
138 /**
139  * @brief Flash Circular Buffer APIs
140  * @defgroup fcb_api fcb API
141  * @ingroup fcb
142  * @{
143  */
144 
145 /**
146  * Initialize FCB instance.
147  *
148  * @param[in] f_area_id ID of flash area where fcb storage resides.
149  * @param[in,out] fcb   FCB instance structure.
150  *
151  * @return 0 on success, non-zero on failure.
152  */
153 int fcb_init(int f_area_id, struct fcb *fcb);
154 
155 /**
156  * Appends an entry to circular buffer.
157  *
158  * When writing the
159  * contents for the entry, use loc->fe_sector and loc->fe_data_off with
160  * flash_area_write() to fcb flash_area.
161  * When you're finished, call fcb_append_finish() with loc as argument.
162  *
163  * @param[in] fcb FCB instance structure.
164  * @param[in] len Length of data which are expected to be written as the entry
165  *            payload.
166  * @param[out] loc entry location information
167  *
168  * @return 0 on success, non-zero on failure.
169  */
170 int fcb_append(struct fcb *fcb, uint16_t len, struct fcb_entry *loc);
171 
172 /**
173  * Finishes entry append operation.
174  *
175  * @param[in] fcb FCB instance structure.
176  * @param[in] append_loc entry location information
177  *
178  * @return 0 on success, non-zero on failure.
179  */
180 int fcb_append_finish(struct fcb *fcb, struct fcb_entry *append_loc);
181 
182 /**
183  * FCB Walk callback function type.
184  *
185  * Type of function which is expected to be called while walking over fcb
186  * entries thanks to a @ref fcb_walk call.
187  *
188  * Entry data can be read using flash_area_read(), using
189  * loc_ctx fields as arguments.
190  * If cb wants to stop the walk, it should return non-zero value.
191  *
192  * @param[in] loc_ctx entry location information (full context)
193  * @param[in,out] arg callback context, transferred from @ref fcb_walk.
194  *
195  * @return 0 continue walking, non-zero stop walking.
196  */
197 typedef int (*fcb_walk_cb)(struct fcb_entry_ctx *loc_ctx, void *arg);
198 
199 /**
200  * Walk over all entries in the FCB sector
201  *
202  * @param[in] sector     fcb sector to be walked. If null, traverse entire
203  *                       storage.
204  * @param[in] fcb        FCB instance structure.
205  * @param[in] cb         pointer to the function which gets called for every
206  *                       entry. If cb wants to stop the walk, it should return
207  *                       non-zero value.
208  * @param[in,out] cb_arg callback context, transferred to the callback
209  *                       implementation.
210  *
211  * @return 0 on success, negative on failure (or transferred form callback
212  *         return-value), positive transferred form callback return-value
213  */
214 int fcb_walk(struct fcb *fcb, struct flash_sector *sector, fcb_walk_cb cb,
215 	     void *cb_arg);
216 
217 /**
218  * Get next fcb entry location.
219  *
220  * Function to obtain fcb entry location in relation to entry pointed by
221  * <p> loc.
222  * If loc->fe_sector is set and loc->fe_elem_off is not 0 function fetches next
223  * fcb entry location.
224  * If loc->fe_sector is NULL function fetches the oldest entry location within
225  * FCB storage. loc->fe_sector is set and loc->fe_elem_off is 0 function fetches
226  * the first entry location in the fcb sector.
227  *
228  * @param[in] fcb FCB instance structure.
229  * @param[in,out] loc entry location information
230  *
231  * @return 0 on success, non-zero on failure.
232  */
233 int fcb_getnext(struct fcb *fcb, struct fcb_entry *loc);
234 
235 /*
236  * Rotate fcb sectors
237  *
238  * Function erases the data from oldest sector. Upon that the next sector
239  * becomes the oldest. Active sector is also switched if needed.
240  *
241  * @param[in] fcb FCB instance structure.
242  */
243 int fcb_rotate(struct fcb *fcb);
244 
245 /*
246  * Start using the scratch block.
247  *
248  * Take one of the scratch blocks into use. So a scratch sector becomes
249  * active sector to which entries can be appended.
250  *
251  * @param[in] fcb FCB instance structure.
252  *
253  * @return 0 on success, non-zero on failure.
254  */
255 int fcb_append_to_scratch(struct fcb *fcb);
256 
257 /**
258  * Get free sector count.
259  *
260  * @param[in] fcb FCB instance structure.
261  *
262  * @return Number of free sectors.
263  */
264 int fcb_free_sector_cnt(struct fcb *fcb);
265 
266 /**
267  * Check whether FCB has any data.
268  *
269  * @param[in] fcb FCB instance structure.
270  *
271  * @return Positive value if fcb is empty, otherwise 0.
272  */
273 int fcb_is_empty(struct fcb *fcb);
274 
275 /**
276  * Finds the fcb entry that gives back up to n entries at the end.
277  *
278  * @param[in]               fcb FCB instance structure.
279  * @param[in] entries       number of fcb entries the user wants to get
280  * @param[out] last_n_entry last_n_entry the fcb_entry to be returned
281  *
282  * @return 0 on there are any fcbs available; -ENOENT otherwise
283  */
284 int fcb_offset_last_n(struct fcb *fcb, uint8_t entries,
285 		      struct fcb_entry *last_n_entry);
286 
287 /**
288  * Clear fcb instance storage.
289  *
290  * @param[in] fcb FCB instance structure.
291  *
292  * @return 0 on success; non-zero on failure
293  */
294 int fcb_clear(struct fcb *fcb);
295 
296 /**
297  * @}
298  */
299 
300 /**
301  * @brief Flash Circular internal
302  * @defgroup fcb_internall fcb non-API prototypes
303  * @ingroup fcb
304  * @{
305  */
306 
307 /**
308  * Read raw data from the fcb flash sector.
309  *
310  * @param[in] fcb    FCB instance structure.
311  * @param[in] sector FCB sector.
312  * @param[in] off    Read offset form sector begin.
313  * @param[out] dst   Destination buffer.
314  * @param[in] len    Read-out size.
315  *
316  * @return  0 on success, negative errno code on fail.
317  */
318 int fcb_flash_read(const struct fcb *fcb, const struct flash_sector *sector,
319 		   off_t off, void *dst, size_t len);
320 
321 /**
322  * Write raw data to the fcb flash sector.
323  *
324  * @param[in] fcb    FCB instance structure.
325  * @param[in] sector FCB sector.
326  * @param[in] off    Write offset form sector begin.
327  * @param[out] src   Source buffer.
328  * @param[in] len    Read-out size.
329  *
330  * @return  0 on success, negative errno code on fail.
331  */
332 int fcb_flash_write(const struct fcb *fcb, const struct flash_sector *sector,
333 		    off_t off, const void *src, size_t len);
334 
335 /**
336  * @}
337  */
338 
339 #ifdef __cplusplus
340 }
341 #endif
342 
343 #endif /* ZEPHYR_INCLUDE_FS_FCB_H_ */
344