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