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