1 /*
2  * Copyright (c) 2017-2024 Nordic Semiconductor ASA
3  * Copyright (c) 2015 Runtime Inc
4  * Copyright (c) 2023 Sensorfy B.V.
5  *
6  * SPDX-License-Identifier: Apache-2.0
7  */
8 
9 /**
10  * @file
11  * @brief Public API for flash map
12  */
13 
14 #ifndef ZEPHYR_INCLUDE_STORAGE_FLASH_MAP_H_
15 #define ZEPHYR_INCLUDE_STORAGE_FLASH_MAP_H_
16 
17 /**
18  * @brief Abstraction over flash partitions/areas and their drivers
19  *
20  * @defgroup flash_area_api flash area Interface
21  * @since 1.11
22  * @version 1.1.0
23  * @ingroup storage_apis
24  * @{
25  */
26 
27 /*
28  * This API makes it possible to operate on flash areas easily and
29  * effectively.
30  *
31  * The system contains global data about flash areas. Every area
32  * contains an ID number, offset, and length.
33  */
34 
35 /**
36  *
37  */
38 #include <zephyr/types.h>
39 #include <stddef.h>
40 #include <sys/types.h>
41 #include <zephyr/device.h>
42 #include <zephyr/devicetree.h>
43 
44 #ifdef __cplusplus
45 extern "C" {
46 #endif
47 
48 /**
49  * @brief Flash partition
50  *
51  * This structure represents a fixed-size partition on a flash device.
52  * Each partition contains one or more flash sectors.
53  */
54 struct flash_area {
55 	/** ID number */
56 	uint8_t fa_id;
57 	uint16_t pad16;
58 	/** Start offset from the beginning of the flash device */
59 	off_t fa_off;
60 	/** Total size */
61 	size_t fa_size;
62 	/** Backing flash device */
63 	const struct device *fa_dev;
64 #if CONFIG_FLASH_MAP_LABELS
65 	/** Partition label if defined in DTS. Otherwise nullptr; */
66 	const char *fa_label;
67 #endif
68 };
69 
70 /**
71  * @brief Structure for transfer flash sector boundaries
72  *
73  * This template is used for presentation of flash memory structure. It
74  * consumes much less RAM than @ref flash_area
75  */
76 struct flash_sector {
77 	/** Sector offset from the beginning of the flash device */
78 	off_t fs_off;
79 	/** Sector size in bytes */
80 	size_t fs_size;
81 };
82 
83 #if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY)
84 /**
85  * @brief Structure for verify flash region integrity
86  *
87  * This is used to pass data to be used to check flash integrity using SHA-256
88  * algorithm.
89  */
90 struct flash_area_check {
91 	const uint8_t *match;		/** 256 bits match vector */
92 	size_t clen;			/** Content len to be compared */
93 	size_t off;			/** Start Offset */
94 	uint8_t *rbuf;			/** Temporary read buffer  */
95 	size_t rblen;			/** Size of read buffer */
96 };
97 
98 /**
99  * Verify flash memory length bytes integrity from a flash area. The start
100  * point is indicated by an offset value.
101  *
102  * @param[in] fa	Flash area
103  * @param[in] fic	Flash area check integrity data
104  *
105  * @return  0 on success, negative errno code on fail
106  */
107 int flash_area_check_int_sha256(const struct flash_area *fa,
108 				const struct flash_area_check *fac);
109 #endif
110 
111 /**
112  * @brief Retrieve partitions flash area from the flash_map.
113  *
114  * Function Retrieves flash_area from flash_map for given partition.
115  *
116  * @param[in]  id ID of the flash partition.
117  * @param[out] fa Pointer which has to reference flash_area. If
118  * @p ID is unknown, it will be NULL on output.
119  *
120  * @return  0 on success, -EACCES if the flash_map is not available ,
121  * -ENOENT if @p ID is unknown, -ENODEV if there is no driver attached
122  * to the area.
123  */
124 int flash_area_open(uint8_t id, const struct flash_area **fa);
125 
126 /**
127  * @brief Close flash_area
128  *
129  * Reserved for future usage and external projects compatibility reason.
130  * Currently is NOP.
131  *
132  * @param[in] fa Flash area to be closed.
133  */
134 void flash_area_close(const struct flash_area *fa);
135 
136 /**
137  * @brief Verify that a device assigned to flash area is ready for use.
138  *
139  * Indicates whether the provided flash area has a device known to be
140  * in a state where it can be used with Flash Map API.
141  *
142  * This can be used with struct flash_area pointers captured from FIXED_PARTITION().
143  * At minimum this means that the device has been successfully initialized.
144  *
145  * @param fa pointer to flash_area object to check.
146  *
147  * @retval true If the device is ready for use.
148  * @retval false If the device is not ready for use or if a NULL pointer is
149  * passed as flash area pointer or device pointer within flash area object
150  * is NULL.
151  */
flash_area_device_is_ready(const struct flash_area * fa)152 static ALWAYS_INLINE bool flash_area_device_is_ready(const struct flash_area *fa)
153 {
154 	return (fa != NULL && device_is_ready(fa->fa_dev));
155 }
156 
157 /**
158  * @brief Read flash area data
159  *
160  * Read data from flash area. Area readout boundaries are asserted before read
161  * request. API has the same limitation regard read-block alignment and size
162  * as wrapped flash driver.
163  *
164  * @param[in]  fa  Flash area
165  * @param[in]  off Offset relative from beginning of flash area to read
166  * @param[out] dst Buffer to store read data
167  * @param[in]  len Number of bytes to read
168  *
169  * @return  0 on success, negative errno code on fail.
170  */
171 int flash_area_read(const struct flash_area *fa, off_t off, void *dst,
172 		    size_t len);
173 
174 /**
175  * @brief Write data to flash area
176  *
177  * Write data to flash area. Area write boundaries are asserted before write
178  * request. API has the same limitation regard write-block alignment and size
179  * as wrapped flash driver.
180  *
181  * @param[in]  fa  Flash area
182  * @param[in]  off Offset relative from beginning of flash area to write
183  * @param[in]  src Buffer with data to be written
184  * @param[in]  len Number of bytes to write
185  *
186  * @return  0 on success, negative errno code on fail.
187  */
188 int flash_area_write(const struct flash_area *fa, off_t off, const void *src,
189 		     size_t len);
190 
191 /**
192  * @brief Copy flash memory from one flash area to another.
193  *
194  * Copy data to flash area. Area boundaries are asserted before copy
195  * request.
196  *
197  * For more information, see flash_copy().
198  *
199  * @param[in]  src_fa  Source Flash area
200  * @param[in]  src_off Offset relative from beginning of source flash area.
201  * @param[in]  dst_fa  Destination Flash area
202  * @param[in]  dst_off Offset relative from beginning of destination flash area.
203  * @param[in]  len Number of bytes to copy, in bytes.
204  * @param[out] buf Pointer to a buffer of size @a buf_size.
205  * @param[in]  buf_size Size of the buffer pointed to by @a buf.
206  *
207  * @return  0 on success, negative errno code on fail.
208  */
209 int flash_area_copy(const struct flash_area *src_fa, off_t src_off,
210 		    const struct flash_area *dst_fa, off_t dst_off,
211 		    off_t len, uint8_t *buf, size_t buf_size);
212 
213 /**
214  * @brief Erase flash area
215  *
216  * Erase given flash area range. Area boundaries are asserted before erase
217  * request. API has the same limitation regard erase-block alignment and size
218  * as wrapped flash driver.
219  *
220  * @param[in] fa  Flash area
221  * @param[in] off Offset relative from beginning of flash area.
222  * @param[in] len Number of bytes to be erase
223  *
224  * @return  0 on success, negative errno code on fail.
225  */
226 int flash_area_erase(const struct flash_area *fa, off_t off, size_t len);
227 
228 /**
229  * @brief Erase flash area or fill with erase-value
230  *
231  * On program-erase devices this function behaves exactly like flash_area_erase.
232  * On RAM non-volatile device it will call erase, if driver provides such
233  * callback, or will fill given range with erase-value defined by driver.
234  * This function should be only used by code that has not been written
235  * to directly support devices that do not require erase and rely on
236  * device being erased prior to some operations.
237  * Note that emulated erase, on devices that do not require, is done
238  * via write, which affects endurance of device.
239  *
240  * @see flash_area_erase()
241  * @see flash_flatten()
242  *
243  * @param[in] fa  Flash area
244  * @param[in] off Offset relative from beginning of flash area.
245  * @param[in] len Number of bytes to be erase
246  *
247  * @return  0 on success, negative errno code on fail.
248  */
249 int flash_area_flatten(const struct flash_area *fa, off_t off, size_t len);
250 
251 /**
252  * @brief Get write block size of the flash area
253  *
254  * Currently write block size might be treated as read block size, although
255  * most of drivers supports unaligned readout.
256  *
257  * @param[in] fa Flash area
258  *
259  * @return Alignment restriction for flash writes in [B].
260  */
261 uint32_t flash_area_align(const struct flash_area *fa);
262 
263 /**
264  * Retrieve info about sectors within the area.
265  *
266  * @param[in]  fa_id    Given flash area ID
267  * @param[in,out] count On input Capacity of @p sectors, on output number of
268  * sectors Retrieved.
269  * @param[out] sectors  buffer for sectors data
270  *
271  * @return  0 on success, negative errno code on fail. Especially returns
272  * -ENOMEM if There are too many flash pages on the flash_area to fit in the
273  * array.
274  */
275 int flash_area_get_sectors(int fa_id, uint32_t *count,
276 			   struct flash_sector *sectors);
277 
278 /**
279  * Retrieve info about sectors within the area.
280  *
281  * @param[in]  fa       pointer to flash area object.
282  * @param[in,out] count On input Capacity of @p sectors, on output number of
283  * sectors retrieved.
284  * @param[out] sectors  buffer for sectors data
285  *
286  * @return  0 on success, negative errno code on fail. Especially returns
287  * -ENOMEM if There are too many flash pages on the flash_area to fit in the
288  * array.
289  */
290 int flash_area_sectors(const struct flash_area *fa, uint32_t *count, struct flash_sector *sectors);
291 
292 /**
293  * Flash map iteration callback
294  *
295  * @param fa flash area
296  * @param user_data User supplied data
297  *
298  */
299 typedef void (*flash_area_cb_t)(const struct flash_area *fa,
300 				void *user_data);
301 
302 /**
303  * Iterate over flash map
304  *
305  * @param user_cb User callback
306  * @param user_data User supplied data
307  */
308 void flash_area_foreach(flash_area_cb_t user_cb, void *user_data);
309 
310 /**
311  * Check whether given flash area has supporting flash driver
312  * in the system.
313  *
314  * @param[in] fa Flash area.
315  *
316  * @return 1 On success. -ENODEV if no driver match.
317  */
318 int flash_area_has_driver(const struct flash_area *fa);
319 
320 /**
321  * Get driver for given flash area.
322  *
323  * @param[in] fa Flash area.
324  *
325  * @return device driver.
326  */
327 const struct device *flash_area_get_device(const struct flash_area *fa);
328 
329 #if CONFIG_FLASH_MAP_LABELS
330 /**
331  * Get the label property from the device tree
332  *
333  * @param[in] fa Flash area.
334  *
335  * @return The label property if it is defined, otherwise NULL
336  */
337 const char *flash_area_label(const struct flash_area *fa);
338 #endif
339 
340 /**
341  * Get the value expected to be read when accessing any erased
342  * flash byte.
343  * This API is compatible with the MCUBoot's porting layer.
344  *
345  * @param fa Flash area.
346  *
347  * @return Byte value of erase memory.
348  */
349 uint8_t flash_area_erased_val(const struct flash_area *fa);
350 
351 /**
352  * Returns non-0 value if fixed-partition or fixed-subpartition of given
353  * DTS node label exists.
354  *
355  * @param label DTS node label
356  *
357  * @return non-0 if fixed-partition node exists and is enabled;
358  *	   0 if node does not exist, is not enabled or is not fixed-partition.
359  */
360 #define FIXED_PARTITION_EXISTS(label) \
361 	UTIL_OR(DT_FIXED_PARTITION_EXISTS(DT_NODELABEL(label)), \
362 		DT_FIXED_SUBPARTITION_EXISTS(DT_NODELABEL(label)))
363 
364 /**
365  * Get flash area ID from fixed-partition DTS node label
366  *
367  * @param label DTS node label of a partition
368  *
369  * @return flash area ID
370  */
371 #define FIXED_PARTITION_ID(label) DT_FIXED_PARTITION_ID(DT_NODELABEL(label))
372 
373 /**
374  * Get fixed-partition or fixed-subpartition offset from DTS node label
375  *
376  * @param label DTS node label of a partition
377  *
378  * @return fixed-partition offset, as defined for the partition in DTS.
379  */
380 #define FIXED_PARTITION_OFFSET(label) DT_REG_ADDR(DT_NODELABEL(label))
381 
382 /**
383  * Get fixed-partition or fixed-subpartition address from DTS node label
384  *
385  * @param label DTS node label of a partition or subpartition
386  *
387  * @return fixed-partition address, as defined for the partition in DTS.
388  */
389 #define FIXED_PARTITION_ADDRESS(label) \
390 	(COND_CODE_1(DT_FIXED_SUBPARTITION_EXISTS(DT_NODELABEL(label)), \
391 		(DT_FIXED_SUBPARTITION_ADDR(DT_NODELABEL(label))), \
392 		(DT_FIXED_PARTITION_ADDR(DT_NODELABEL(label)))))
393 
394 /**
395  * Get fixed-partition or fixed-subpartition address from DTS node
396  *
397  * @param node DTS node of a partition
398  *
399  * @return fixed-partition address, as defined for the partition in DTS.
400  */
401 #define FIXED_PARTITION_NODE_ADDRESS(node) \
402 	(COND_CODE_1(DT_FIXED_SUBPARTITION_EXISTS(node), \
403 		(DT_FIXED_SUBPARTITION_ADDR(node)), \
404 		(DT_FIXED_PARTITION_ADDR(node))))
405 
406 /**
407  * Get fixed-partition offset from DTS node
408  *
409  * @param node DTS node of a partition
410  *
411  * @return fixed-partition offset, as defined for the partition in DTS.
412  */
413 #define FIXED_PARTITION_NODE_OFFSET(node) DT_REG_ADDR(node)
414 
415 /**
416  * Get fixed-partition size for DTS node label
417  *
418  * @param label DTS node label
419  *
420  * @return fixed-partition offset, as defined for the partition in DTS.
421  */
422 #define FIXED_PARTITION_SIZE(label) DT_REG_SIZE(DT_NODELABEL(label))
423 
424 /**
425  * Get fixed-partition size for DTS node
426  *
427  * @param node DTS node of a partition
428  *
429  * @return fixed-partition size, as defined for the partition in DTS.
430  */
431 #define FIXED_PARTITION_NODE_SIZE(node) DT_REG_SIZE(node)
432 
433 /**
434  * Get device pointer for device the area/partition resides on
435  *
436  * @param label DTS node label of a partition
437  *
438  * @return const struct device type pointer
439  */
440 #define FLASH_AREA_DEVICE(label) \
441 	DEVICE_DT_GET(DT_MTD_FROM_FIXED_PARTITION(DT_NODE_BY_FIXED_PARTITION_LABEL(label)))
442 
443 /**
444  * Get device pointer for device the area/partition resides on
445  *
446  * @param label DTS node label of a partition
447  *
448  * @return Pointer to a device.
449  */
450 #define FIXED_PARTITION_DEVICE(label) \
451 	DEVICE_DT_GET(COND_CODE_1( \
452 		DT_FIXED_SUBPARTITION_EXISTS(DT_NODELABEL(label)), \
453 			(DT_MTD_FROM_FIXED_SUBPARTITION(DT_NODELABEL(label))), \
454 			(DT_MTD_FROM_FIXED_PARTITION(DT_NODELABEL(label)))))
455 /**
456  * Get device pointer for device the area/partition resides on
457  *
458  * @param node DTS node of a partition
459  *
460  * @return Pointer to a device.
461  */
462 #define FIXED_PARTITION_NODE_DEVICE(node) \
463 	DEVICE_DT_GET(COND_CODE_1( \
464 		DT_FIXED_SUBPARTITION_EXISTS(node), \
465 			(DT_MTD_FROM_FIXED_SUBPARTITION(node)), \
466 			(DT_MTD_FROM_FIXED_PARTITION(node))))
467 
468 /**
469  * Get the node identifier of the flash controller the area/partition resides on
470  *
471  * @param label DTS node label of a partition
472  *
473  * @return Pointer to a device.
474  */
475 #define FIXED_PARTITION_MTD(label) \
476 	COND_CODE_1( \
477 		DT_FIXED_SUBPARTITION_EXISTS(DT_NODELABEL(label)), \
478 			(DT_MTD_FROM_FIXED_SUBPARTITION(DT_NODELABEL(label))), \
479 			(DT_MTD_FROM_FIXED_PARTITION(DT_NODELABEL(label))))
480 
481 /**
482  * Get the node identifier of the flash controller the area/partition resides on
483  *
484  * @param node DTS node of a partition
485  *
486  * @return Pointer to a device.
487  */
488 #define FIXED_PARTITION_NODE_MTD(node) \
489 	COND_CODE_1( \
490 		DT_FIXED_SUBPARTITION_EXISTS(node), \
491 			(DT_MTD_FROM_FIXED_SUBPARTITION(node)), \
492 			(DT_MTD_FROM_FIXED_PARTITION(node)))
493 
494 /**
495  * Get pointer to flash_area object by partition label
496  *
497  * @param label DTS node label of a partition
498  *
499  * @return Pointer to flash_area type object representing partition
500  */
501 #define FIXED_PARTITION(label)	FIXED_PARTITION_1(DT_NODELABEL(label))
502 
503 /**
504  * Get pointer to flash_area object by partition node in DTS
505  *
506  * @param node DTS node of a partition
507  *
508  * @return Pointer to flash_area type object representing partition
509  */
510 #define FIXED_PARTITION_BY_NODE(node)	FIXED_PARTITION_1(node)
511 
512 /** @cond INTERNAL_HIDDEN */
513 #define FIXED_PARTITION_1(node)	FIXED_PARTITION_0(DT_DEP_ORD(node))
514 #define FIXED_PARTITION_0(ord)							\
515 	((const struct flash_area *)&DT_CAT(global_fixed_partition_ORD_, ord))
516 
517 #define DECLARE_PARTITION(node) DECLARE_PARTITION_0(DT_DEP_ORD(node))
518 #define DECLARE_PARTITION_0(ord)						\
519 	extern const struct flash_area DT_CAT(global_fixed_partition_ORD_, ord);
520 #define FOR_EACH_PARTITION_TABLE(table) DT_FOREACH_CHILD(table, DECLARE_PARTITION)
521 
522 /* Generate declarations */
523 DT_FOREACH_STATUS_OKAY(fixed_partitions, FOR_EACH_PARTITION_TABLE)
524 
525 #undef DECLARE_PARTITION
526 #undef DECLARE_PARTITION_0
527 #undef FOR_EACH_PARTITION_TABLE
528 
529 #define FIXED_SUBPARTITION_1(node) FIXED_SUBPARTITION_0(DT_DEP_ORD(node))
530 #define FIXED_SUBPARTITION_0(ord)						\
531 	((const struct flash_area *)&DT_CAT(global_fixed_subpartition_ORD_, ord))
532 
533 #define DECLARE_SUBPARTITION(node) DECLARE_SUBPARTITION_0(DT_DEP_ORD(node))
534 #define DECLARE_SUBPARTITION_0(ord)						\
535 	extern const struct flash_area DT_CAT(global_fixed_subpartition_ORD_, ord);
536 #define FOR_EACH_SUBPARTITION_TABLE(table) DT_FOREACH_CHILD(table, DECLARE_SUBPARTITION)
537 
538 /* Generate declarations */
539 DT_FOREACH_STATUS_OKAY(fixed_subpartitions, FOR_EACH_SUBPARTITION_TABLE)
540 
541 #undef DECLARE_SUBPARTITION
542 #undef DECLARE_SUBPARTITION_0
543 #undef FOR_EACH_SUBPARTITION_TABLE
544 /** @endcond */
545 
546 #ifdef __cplusplus
547 }
548 #endif
549 
550 /**
551  * @}
552  */
553 
554 #endif /* ZEPHYR_INCLUDE_STORAGE_FLASH_MAP_H_ */
555