1 /* Copyright (c) 2018 Laczen 2 * Copyright (c) 2024 BayLibre SAS 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * ZMS: Zephyr Memory Storage 7 */ 8 #ifndef ZEPHYR_INCLUDE_FS_ZMS_H_ 9 #define ZEPHYR_INCLUDE_FS_ZMS_H_ 10 11 #include <sys/types.h> 12 #include <zephyr/drivers/flash.h> 13 #include <zephyr/kernel.h> 14 #include <zephyr/device.h> 15 #include <zephyr/toolchain.h> 16 17 #ifdef __cplusplus 18 extern "C" { 19 #endif 20 21 /** 22 * @defgroup zms Zephyr Memory Storage (ZMS) 23 * @ingroup file_system_storage 24 * @{ 25 * @} 26 */ 27 28 /** 29 * @defgroup zms_data_structures ZMS data structures 30 * @ingroup zms 31 * @{ 32 */ 33 34 /** Zephyr Memory Storage file system structure */ 35 struct zms_fs { 36 /** File system offset in flash */ 37 off_t offset; 38 /** Allocation Table Entry (ATE) write address. 39 * Addresses are stored as `uint64_t`: 40 * - high 4 bytes correspond to the sector 41 * - low 4 bytes are the offset in the sector 42 */ 43 uint64_t ate_wra; 44 /** Data write address */ 45 uint64_t data_wra; 46 /** Storage system is split into sectors. The sector size must be a multiple of 47 * `erase-block-size` if the device has erase capabilities 48 */ 49 uint32_t sector_size; 50 /** Number of sectors in the file system */ 51 uint32_t sector_count; 52 /** Current cycle counter of the active sector (pointed to by `ate_wra`) */ 53 uint8_t sector_cycle; 54 /** Flag indicating if the file system is initialized */ 55 bool ready; 56 /** Mutex used to lock flash writes */ 57 struct k_mutex zms_lock; 58 /** Flash device runtime structure */ 59 const struct device *flash_device; 60 /** Flash memory parameters structure */ 61 const struct flash_parameters *flash_parameters; 62 /** Size of an Allocation Table Entry */ 63 size_t ate_size; 64 #if CONFIG_ZMS_LOOKUP_CACHE 65 /** Lookup table used to cache ATE addresses of written IDs */ 66 uint64_t lookup_cache[CONFIG_ZMS_LOOKUP_CACHE_SIZE]; 67 #endif 68 }; 69 70 /** 71 * @} 72 */ 73 74 /** 75 * @defgroup zms_high_level_api ZMS API 76 * @ingroup zms 77 * @{ 78 */ 79 80 /** 81 * @brief Mount a ZMS file system onto the device specified in `fs`. 82 * 83 * @param fs Pointer to the file system. 84 * 85 * @retval 0 on success. 86 * @retval -ENOTSUP if the detected file system is not ZMS. 87 * @retval -EPROTONOSUPPORT if the ZMS version is not supported. 88 * @retval -EINVAL if any of the flash parameters or the sector layout is invalid. 89 * @retval -ENXIO if there is a device error. 90 * @retval -EIO if there is a memory read/write error. 91 */ 92 int zms_mount(struct zms_fs *fs); 93 94 /** 95 * @brief Clear the ZMS file system from device. 96 * 97 * @param fs Pointer to the file system. 98 * 99 * @retval 0 on success. 100 * @retval -EACCES if `fs` is not mounted. 101 * @retval -ENXIO if there is a device error. 102 * @retval -EIO if there is a memory read/write error. 103 */ 104 int zms_clear(struct zms_fs *fs); 105 106 /** 107 * @brief Write an entry to the file system. 108 * 109 * @note When the `len` parameter is equal to `0` the entry is effectively removed (it is 110 * equivalent to calling @ref zms_delete()). It is not possible to distinguish between a deleted 111 * entry and an entry with data of length 0. 112 * 113 * @param fs Pointer to the file system. 114 * @param id ID of the entry to be written. 115 * @param data Pointer to the data to be written. 116 * @param len Number of bytes to be written (maximum 64 KiB). 117 * 118 * @return Number of bytes written. On success, it will be equal to the number of bytes requested 119 * to be written or 0. 120 * When a rewrite of the same data already stored is attempted, nothing is written to flash, 121 * thus 0 is returned. On error, returns negative value of error codes defined in `errno.h`. 122 * @retval Number of bytes written (`len` or 0) on success. 123 * @retval -EACCES if ZMS is still not initialized. 124 * @retval -ENXIO if there is a device error. 125 * @retval -EIO if there is a memory read/write error. 126 * @retval -EINVAL if `len` is invalid. 127 * @retval -ENOSPC if no space is left on the device. 128 */ 129 ssize_t zms_write(struct zms_fs *fs, uint32_t id, const void *data, size_t len); 130 131 /** 132 * @brief Delete an entry from the file system 133 * 134 * @param fs Pointer to the file system. 135 * @param id ID of the entry to be deleted. 136 * 137 * @retval 0 on success. 138 * @retval -EACCES if ZMS is still not initialized. 139 * @retval -ENXIO if there is a device error. 140 * @retval -EIO if there is a memory read/write error. 141 */ 142 int zms_delete(struct zms_fs *fs, uint32_t id); 143 144 /** 145 * @brief Read an entry from the file system. 146 * 147 * @param fs Pointer to the file system. 148 * @param id ID of the entry to be read. 149 * @param data Pointer to data buffer. 150 * @param len Number of bytes to read at most. 151 * 152 * @return Number of bytes read. On success, it will be equal to the number of bytes requested 153 * to be read or less than that if the stored data has a smaller size than the requested one. 154 * On error, returns negative value of error codes defined in `errno.h`. 155 * @retval Number of bytes read (> 0) on success. 156 * @retval -EACCES if ZMS is still not initialized. 157 * @retval -EIO if there is a memory read/write error. 158 * @retval -ENOENT if there is no entry with the given `id`. 159 */ 160 ssize_t zms_read(struct zms_fs *fs, uint32_t id, void *data, size_t len); 161 162 /** 163 * @brief Read a history entry from the file system. 164 * 165 * @param fs Pointer to the file system. 166 * @param id ID of the entry to be read. 167 * @param data Pointer to data buffer. 168 * @param len Number of bytes to be read. 169 * @param cnt History counter: 0: latest entry, 1: one before latest ... 170 * 171 * @return Number of bytes read. On success, it will be equal to the number of bytes requested 172 * to be read. When the return value is larger than the number of bytes requested to read this 173 * indicates not all bytes were read, and more data is available. On error, returns negative 174 * value of error codes defined in `errno.h`. 175 * @retval Number of bytes read (> 0) on success. 176 * @retval -EACCES if ZMS is still not initialized. 177 * @retval -EIO if there is a memory read/write error. 178 * @retval -ENOENT if there is no entry with the given `id` and history counter. 179 */ 180 ssize_t zms_read_hist(struct zms_fs *fs, uint32_t id, void *data, size_t len, uint32_t cnt); 181 182 /** 183 * @brief Gets the length of the data that is stored in an entry with a given `id` 184 * 185 * @param fs Pointer to the file system. 186 * @param id ID of the entry whose data length to retrieve. 187 * 188 * @return Data length contained in the ATE. On success, it will be equal to the number of bytes 189 * in the ATE. On error, returns negative value of error codes defined in `errno.h`. 190 * @retval Length of the entry with the given `id` (> 0) on success. 191 * @retval -EACCES if ZMS is still not initialized. 192 * @retval -EIO if there is a memory read/write error. 193 * @retval -ENOENT if there is no entry with the given id and history counter. 194 */ 195 ssize_t zms_get_data_length(struct zms_fs *fs, uint32_t id); 196 197 /** 198 * @brief Calculate the available free space in the file system. 199 * 200 * @param fs Pointer to the file system. 201 * 202 * @return Number of free bytes. On success, it will be equal to the number of bytes that can 203 * still be written to the file system. 204 * Calculating the free space is a time-consuming operation, especially on SPI flash. 205 * On error, returns negative value of error codes defined in `errno.h`. 206 * @retval Number of free bytes (>= 0) on success. 207 * @retval -EACCES if ZMS is still not initialized. 208 * @retval -EIO if there is a memory read/write error. 209 */ 210 ssize_t zms_calc_free_space(struct zms_fs *fs); 211 212 /** 213 * @brief Tell how much contiguous free space remains in the currently active ZMS sector. 214 * 215 * @param fs Pointer to the file system. 216 * 217 * @retval >=0 Number of free bytes in the currently active sector 218 * @retval -EACCES if ZMS is still not initialized. 219 */ 220 size_t zms_active_sector_free_space(struct zms_fs *fs); 221 222 /** 223 * @brief Close the currently active sector and switch to the next one. 224 * 225 * @note The garbage collector is called on the new sector. 226 * 227 * @warning This routine is made available for specific use cases. 228 * It collides with ZMS's goal of avoiding any unnecessary flash erase operations. 229 * Using this routine extensively can result in premature failure of the flash device. 230 * 231 * @param fs Pointer to the file system. 232 * 233 * @retval 0 on success. 234 * @retval -EACCES if ZMS is still not initialized. 235 * @retval -EIO if there is a memory read/write error. 236 */ 237 int zms_sector_use_next(struct zms_fs *fs); 238 239 /** 240 * @} 241 */ 242 243 #ifdef __cplusplus 244 } 245 #endif 246 247 #endif /* ZEPHYR_INCLUDE_FS_ZMS_H_ */ 248