/* * Copyright (c) 2017-2024 Nordic Semiconductor ASA * Copyright (c) 2015 Runtime Inc * Copyright (c) 2023 Sensorfy B.V. * * SPDX-License-Identifier: Apache-2.0 */ /** * @file * @brief Public API for flash map */ #ifndef ZEPHYR_INCLUDE_STORAGE_FLASH_MAP_H_ #define ZEPHYR_INCLUDE_STORAGE_FLASH_MAP_H_ /** * @brief Abstraction over flash partitions/areas and their drivers * * @defgroup flash_area_api flash area Interface * @since 1.11 * @version 1.0.0 * @ingroup storage_apis * @{ */ /* * This API makes it possible to operate on flash areas easily and * effectively. * * The system contains global data about flash areas. Every area * contains an ID number, offset, and length. */ /** * */ #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif /** * @brief Flash partition * * This structure represents a fixed-size partition on a flash device. * Each partition contains one or more flash sectors. */ struct flash_area { /** ID number */ uint8_t fa_id; uint16_t pad16; /** Start offset from the beginning of the flash device */ off_t fa_off; /** Total size */ size_t fa_size; /** Backing flash device */ const struct device *fa_dev; #if CONFIG_FLASH_MAP_LABELS /** Partition label if defined in DTS. Otherwise nullptr; */ const char *fa_label; #endif }; /** * @brief Structure for transfer flash sector boundaries * * This template is used for presentation of flash memory structure. It * consumes much less RAM than @ref flash_area */ struct flash_sector { /** Sector offset from the beginning of the flash device */ off_t fs_off; /** Sector size in bytes */ size_t fs_size; }; #if defined(CONFIG_FLASH_AREA_CHECK_INTEGRITY) /** * @brief Structure for verify flash region integrity * * This is used to pass data to be used to check flash integrity using SHA-256 * algorithm. */ struct flash_area_check { const uint8_t *match; /** 256 bits match vector */ size_t clen; /** Content len to be compared */ size_t off; /** Start Offset */ uint8_t *rbuf; /** Temporary read buffer */ size_t rblen; /** Size of read buffer */ }; /** * Verify flash memory length bytes integrity from a flash area. The start * point is indicated by an offset value. * * @param[in] fa Flash area * @param[in] fic Flash area check integrity data * * @return 0 on success, negative errno code on fail */ int flash_area_check_int_sha256(const struct flash_area *fa, const struct flash_area_check *fac); #endif /** * @brief Retrieve partitions flash area from the flash_map. * * Function Retrieves flash_area from flash_map for given partition. * * @param[in] id ID of the flash partition. * @param[out] fa Pointer which has to reference flash_area. If * @p ID is unknown, it will be NULL on output. * * @return 0 on success, -EACCES if the flash_map is not available , * -ENOENT if @p ID is unknown, -ENODEV if there is no driver attached * to the area. */ int flash_area_open(uint8_t id, const struct flash_area **fa); /** * @brief Close flash_area * * Reserved for future usage and external projects compatibility reason. * Currently is NOP. * * @param[in] fa Flash area to be closed. */ void flash_area_close(const struct flash_area *fa); /** * @brief Verify that a device assigned to flash area is ready for use. * * Indicates whether the provided flash area has a device known to be * in a state where it can be used with Flash Map API. * * This can be used with struct flash_area pointers captured from FIXED_PARTITION(). * At minimum this means that the device has been successfully initialized. * * @param fa pointer to flash_area object to check. * * @retval true If the device is ready for use. * @retval false If the device is not ready for use or if a NULL pointer is * passed as flash area pointer or device pointer within flash area object * is NULL. */ static ALWAYS_INLINE bool flash_area_device_is_ready(const struct flash_area *fa) { return (fa != NULL && device_is_ready(fa->fa_dev)); } /** * @brief Read flash area data * * Read data from flash area. Area readout boundaries are asserted before read * request. API has the same limitation regard read-block alignment and size * as wrapped flash driver. * * @param[in] fa Flash area * @param[in] off Offset relative from beginning of flash area to read * @param[out] dst Buffer to store read data * @param[in] len Number of bytes to read * * @return 0 on success, negative errno code on fail. */ int flash_area_read(const struct flash_area *fa, off_t off, void *dst, size_t len); /** * @brief Write data to flash area * * Write data to flash area. Area write boundaries are asserted before write * request. API has the same limitation regard write-block alignment and size * as wrapped flash driver. * * @param[in] fa Flash area * @param[in] off Offset relative from beginning of flash area to write * @param[in] src Buffer with data to be written * @param[in] len Number of bytes to write * * @return 0 on success, negative errno code on fail. */ int flash_area_write(const struct flash_area *fa, off_t off, const void *src, size_t len); /** * @brief Erase flash area * * Erase given flash area range. Area boundaries are asserted before erase * request. API has the same limitation regard erase-block alignment and size * as wrapped flash driver. * * @param[in] fa Flash area * @param[in] off Offset relative from beginning of flash area. * @param[in] len Number of bytes to be erase * * @return 0 on success, negative errno code on fail. */ int flash_area_erase(const struct flash_area *fa, off_t off, size_t len); /** * @brief Erase flash area or fill with erase-value * * On program-erase devices this function behaves exactly like flash_area_erase. * On RAM non-volatile device it will call erase, if driver provides such * callback, or will fill given range with erase-value defined by driver. * This function should be only used by code that has not been written * to directly support devices that do not require erase and rely on * device being erased prior to some operations. * Note that emulated erase, on devices that do not require, is done * via write, which affects endurance of device. * * @see flash_area_erase() * @see flash_flatten() * * @param[in] fa Flash area * @param[in] off Offset relative from beginning of flash area. * @param[in] len Number of bytes to be erase * * @return 0 on success, negative errno code on fail. */ int flash_area_flatten(const struct flash_area *fa, off_t off, size_t len); /** * @brief Get write block size of the flash area * * Currently write block size might be treated as read block size, although * most of drivers supports unaligned readout. * * @param[in] fa Flash area * * @return Alignment restriction for flash writes in [B]. */ uint32_t flash_area_align(const struct flash_area *fa); /** * Retrieve info about sectors within the area. * * @param[in] fa_id Given flash area ID * @param[in,out] count On input Capacity of @p sectors, on output number of * sectors Retrieved. * @param[out] sectors buffer for sectors data * * @return 0 on success, negative errno code on fail. Especially returns * -ENOMEM if There are too many flash pages on the flash_area to fit in the * array. */ int flash_area_get_sectors(int fa_id, uint32_t *count, struct flash_sector *sectors); /** * Retrieve info about sectors within the area. * * @param[in] fa pointer to flash area object. * @param[in,out] count On input Capacity of @p sectors, on output number of * sectors retrieved. * @param[out] sectors buffer for sectors data * * @return 0 on success, negative errno code on fail. Especially returns * -ENOMEM if There are too many flash pages on the flash_area to fit in the * array. */ int flash_area_sectors(const struct flash_area *fa, uint32_t *count, struct flash_sector *sectors); /** * Flash map iteration callback * * @param fa flash area * @param user_data User supplied data * */ typedef void (*flash_area_cb_t)(const struct flash_area *fa, void *user_data); /** * Iterate over flash map * * @param user_cb User callback * @param user_data User supplied data */ void flash_area_foreach(flash_area_cb_t user_cb, void *user_data); /** * Check whether given flash area has supporting flash driver * in the system. * * @param[in] fa Flash area. * * @return 1 On success. -ENODEV if no driver match. */ int flash_area_has_driver(const struct flash_area *fa); /** * Get driver for given flash area. * * @param[in] fa Flash area. * * @return device driver. */ const struct device *flash_area_get_device(const struct flash_area *fa); #if CONFIG_FLASH_MAP_LABELS /** * Get the label property from the device tree * * @param[in] fa Flash area. * * @return The label property if it is defined, otherwise NULL */ const char *flash_area_label(const struct flash_area *fa); #endif /** * Get the value expected to be read when accessing any erased * flash byte. * This API is compatible with the MCUBoot's porting layer. * * @param fa Flash area. * * @return Byte value of erase memory. */ uint8_t flash_area_erased_val(const struct flash_area *fa); /** * Returns non-0 value if fixed-partition of given DTS node label exists. * * @param label DTS node label * * @return non-0 if fixed-partition node exists and is enabled; * 0 if node does not exist, is not enabled or is not fixed-partition. */ #define FIXED_PARTITION_EXISTS(label) DT_FIXED_PARTITION_EXISTS(DT_NODELABEL(label)) /** * Get flash area ID from fixed-partition DTS node label * * @param label DTS node label of a partition * * @return flash area ID */ #define FIXED_PARTITION_ID(label) DT_FIXED_PARTITION_ID(DT_NODELABEL(label)) /** * Get fixed-partition offset from DTS node label * * @param label DTS node label of a partition * * @return fixed-partition offset, as defined for the partition in DTS. */ #define FIXED_PARTITION_OFFSET(label) DT_REG_ADDR(DT_NODELABEL(label)) /** * Get fixed-partition offset from DTS node * * @param node DTS node of a partition * * @return fixed-partition offset, as defined for the partition in DTS. */ #define FIXED_PARTITION_NODE_OFFSET(node) DT_REG_ADDR(node) /** * Get fixed-partition size for DTS node label * * @param label DTS node label * * @return fixed-partition offset, as defined for the partition in DTS. */ #define FIXED_PARTITION_SIZE(label) DT_REG_SIZE(DT_NODELABEL(label)) /** * Get fixed-partition size for DTS node * * @param node DTS node of a partition * * @return fixed-partition size, as defined for the partition in DTS. */ #define FIXED_PARTITION_NODE_SIZE(node) DT_REG_SIZE(node) /** * Get device pointer for device the area/partition resides on * * @param label DTS node label of a partition * * @return const struct device type pointer */ #define FLASH_AREA_DEVICE(label) \ DEVICE_DT_GET(DT_MTD_FROM_FIXED_PARTITION(DT_NODE_BY_FIXED_PARTITION_LABEL(label))) /** * Get device pointer for device the area/partition resides on * * @param label DTS node label of a partition * * @return Pointer to a device. */ #define FIXED_PARTITION_DEVICE(label) \ DEVICE_DT_GET(DT_MTD_FROM_FIXED_PARTITION(DT_NODELABEL(label))) /** * Get device pointer for device the area/partition resides on * * @param node DTS node of a partition * * @return Pointer to a device. */ #define FIXED_PARTITION_NODE_DEVICE(node) \ DEVICE_DT_GET(DT_MTD_FROM_FIXED_PARTITION(node)) /** * Get pointer to flash_area object by partition label * * @param label DTS node label of a partition * * @return Pointer to flash_area type object representing partition */ #define FIXED_PARTITION(label) FIXED_PARTITION_1(DT_NODELABEL(label)) /** * Get pointer to flash_area object by partition node in DTS * * @param node DTS node of a partition * * @return Pointer to flash_area type object representing partition */ #define FIXED_PARTITION_BY_NODE(node) FIXED_PARTITION_1(node) /** @cond INTERNAL_HIDDEN */ #define FIXED_PARTITION_1(node) FIXED_PARTITION_0(DT_DEP_ORD(node)) #define FIXED_PARTITION_0(ord) \ ((const struct flash_area *)&DT_CAT(global_fixed_partition_ORD_, ord)) #define DECLARE_PARTITION(node) DECLARE_PARTITION_0(DT_DEP_ORD(node)) #define DECLARE_PARTITION_0(ord) \ extern const struct flash_area DT_CAT(global_fixed_partition_ORD_, ord); #define FOR_EACH_PARTITION_TABLE(table) DT_FOREACH_CHILD(table, DECLARE_PARTITION) /* Generate declarations */ DT_FOREACH_STATUS_OKAY(fixed_partitions, FOR_EACH_PARTITION_TABLE) #undef DECLARE_PARTITION #undef DECLARE_PARTITION_0 #undef FOR_EACH_PARTITION_TABLE /** @endcond */ #ifdef __cplusplus } #endif /** * @} */ #endif /* ZEPHYR_INCLUDE_STORAGE_FLASH_MAP_H_ */