1 /* 2 * Copyright (c) 2018-2021, Arm Limited. All rights reserved. 3 * 4 * SPDX-License-Identifier: BSD-3-Clause 5 * 6 */ 7 8 #ifndef __ITS_FLASH_FS_MBLOCK_H__ 9 #define __ITS_FLASH_FS_MBLOCK_H__ 10 11 #include <stdbool.h> 12 #include <stddef.h> 13 #include <stdint.h> 14 15 #include "flash/its_flash.h" 16 #include "its_flash_fs.h" 17 #include "its_utils.h" 18 #include "psa/error.h" 19 20 #ifdef __cplusplus 21 extern "C" { 22 #endif 23 24 /*! 25 * \def ITS_SUPPORTED_VERSION 26 * 27 * \brief Defines the supported version. 28 */ 29 #define ITS_SUPPORTED_VERSION 0x02 30 31 /*! 32 * \def ITS_BACKWARD_SUPPORTED_VERSION 33 * 34 * \brief Defines the backward supported version. 35 */ 36 #define ITS_BACKWARD_SUPPORTED_VERSION 0x01 37 38 /*! 39 * \def ITS_METADATA_INVALID_INDEX 40 * 41 * \brief Defines the invalid index value when the metadata table is full 42 */ 43 #define ITS_METADATA_INVALID_INDEX 0xFFFF 44 45 /*! 46 * \def ITS_LOGICAL_DBLOCK0 47 * 48 * \brief Defines logical data block 0 ID 49 */ 50 #define ITS_LOGICAL_DBLOCK0 0 51 52 /*! 53 * \struct its_metadata_block_header_t 54 * 55 * \brief Structure to store the metadata block header. 56 * 57 * \note The active_swap_count must be the last member to allow it to be 58 * programmed last. 59 * The fs_version must be at the same position as it is in 60 * its_metadata_block_header_comp_t. 61 * 62 * \note This structure is programmed to flash, so its size must be padded 63 * to a multiple of the maximum required flash program unit. 64 */ 65 #define _T1 \ 66 uint32_t scratch_dblock; /*!< Physical block ID of the data \ 67 * section's scratch block \ 68 */ \ 69 uint8_t fs_version; /*!< Filesystem version */ \ 70 uint8_t metadata_xor; /*!< XOR value based on the whole metadata(not \ 71 * including the metadata block header) \ 72 */ \ 73 uint8_t active_swap_count; /*!< Number of times the metadata blocks have \ 74 * been swapped \ 75 */ 76 77 struct its_metadata_block_header_t { 78 _T1 79 #if ((ITS_FLASH_MAX_ALIGNMENT) > 4) 80 uint8_t roundup[sizeof(struct __attribute__((__aligned__(ITS_FLASH_MAX_ALIGNMENT))) { _T1 }) - 81 sizeof(struct { _T1 })]; /*!< _T1 has aligned to the maximum 82 * field scratch_dblock which is 83 * 4 bytes. 84 */ 85 #endif 86 }; 87 #undef _T1 88 89 /*! 90 * \struct its_metadata_block_header_comp_t 91 * 92 * \brief The struture of metadata block header in 93 * ITS_BACKWARD_SUPPORTED_VERSION. 94 * 95 * \note The active_swap_count must be the last member to allow it to be 96 * programmed last. 97 * 98 * \note This structure is programmed to flash, so its size must be padded 99 * to a multiple of the maximum required flash program unit. 100 */ 101 #define _T1_COMP \ 102 uint32_t scratch_dblock; /*!< Physical block ID of the data \ 103 * section's scratch block \ 104 */ \ 105 uint8_t fs_version; /*!< Filesystem version */ \ 106 uint8_t active_swap_count; /*!< Number of times the metadata blocks have \ 107 * been swapped \ 108 */ 109 110 struct its_metadata_block_header_comp_t { 111 _T1_COMP 112 #if ((ITS_FLASH_MAX_ALIGNMENT) > 4) 113 uint8_t roundup[sizeof(struct __attribute__((__aligned__(ITS_FLASH_MAX_ALIGNMENT))) { _T1_COMP }) - 114 sizeof(struct { _T1_COMP })]; 115 #endif 116 }; 117 #undef _T1_COMP 118 119 /*! 120 * \struct its_block_meta_t 121 * 122 * \brief Structure to store information about each physical flash memory block. 123 * 124 * \note This structure is programmed to flash, so its size must be padded 125 * to a multiple of the maximum required flash program unit. 126 */ 127 #define _T2 \ 128 uint32_t phy_id; /*!< Physical ID of this logical block */ \ 129 size_t data_start; /*!< Offset from the beginning of the block to the \ 130 * location where the data starts \ 131 */ \ 132 size_t free_size; /*!< Number of bytes free at end of block (set during \ 133 * block compaction for gap reuse) \ 134 */ 135 136 struct its_block_meta_t { 137 _T2 138 #if ((ITS_FLASH_MAX_ALIGNMENT) > 4) 139 uint8_t roundup[sizeof(struct __attribute__((__aligned__(ITS_FLASH_MAX_ALIGNMENT))) { _T2 }) - 140 sizeof(struct { _T2 })]; 141 #endif 142 }; 143 #undef _T2 144 145 /*! 146 * \struct its_file_meta_t 147 * 148 * \brief Structure to store file metadata. 149 * 150 * \note This structure is programmed to flash, so its size must be padded 151 * to a multiple of the maximum required flash program unit. 152 */ 153 #ifdef ITS_ENCRYPTION 154 #define _T3 \ 155 uint32_t lblock; /* Logical datablock where file is stored */ \ 156 size_t data_idx; /* Offset in the logical data block */ \ 157 size_t cur_size; /* Size in storage system for this fragment */ \ 158 size_t max_size; /* Maximum size of this file */ \ 159 uint32_t flags; /* Flags set when the file was created */ \ 160 uint8_t id[ITS_FILE_ID_SIZE]; /* ID of this file */ \ 161 uint8_t nonce[TFM_ITS_ENC_NONCE_LENGTH]; \ 162 uint8_t tag[TFM_ITS_AUTH_TAG_LENGTH] 163 #else 164 #define _T3 \ 165 uint32_t lblock; /* Logical datablock where file is stored */ \ 166 size_t data_idx; /* Offset in the logical data block */ \ 167 size_t cur_size; /* Size in storage system for this fragment */ \ 168 size_t max_size; /* Maximum size of this file */ \ 169 uint32_t flags; /* Flags set when the file was created */ \ 170 uint8_t id[ITS_FILE_ID_SIZE] /* ID of this file */ 171 #endif 172 173 struct its_file_meta_t { 174 _T3; 175 #if ((ITS_FLASH_MAX_ALIGNMENT) > 4) 176 uint8_t roundup[sizeof(struct __attribute__((__aligned__(ITS_FLASH_MAX_ALIGNMENT))) { _T3; }) - 177 sizeof(struct { _T3; })]; 178 #endif 179 }; 180 #undef _T3 181 182 /** 183 * \struct its_flash_fs_ctx_t 184 * 185 * \brief Structure to store the ITS flash file system context. 186 */ 187 struct its_flash_fs_ctx_t { 188 const struct its_flash_fs_config_t *cfg; /**< Filesystem configuration */ 189 const struct its_flash_fs_ops_t *ops; /**< Filesystem flash operations */ 190 struct its_metadata_block_header_t meta_block_header; /**< Metadata block 191 * header 192 */ 193 uint32_t active_metablock; /**< Active metadata block */ 194 uint32_t scratch_metablock; /**< Scratch metadata block */ 195 }; 196 197 /** 198 * \brief Initializes metadata block with the valid/active metablock. 199 * 200 * \param[in,out] fs_ctx Filesystem context 201 * 202 * \return Returns value as specified in \ref psa_status_t 203 */ 204 psa_status_t its_flash_fs_mblock_init(struct its_flash_fs_ctx_t *fs_ctx); 205 206 /** 207 * \brief Copies the file metadata entries between two indexes from the active 208 * metadata block to the scratch metadata block. 209 * 210 * \param[in,out] fs_ctx Filesystem context 211 * \param[in] idx_start File metadata entry index to start copy, inclusive 212 * \param[in] idx_end File metadata entry index to end copy, exclusive 213 * 214 * \return Returns error code as specified in \ref psa_status_t 215 */ 216 psa_status_t its_flash_fs_mblock_cp_file_meta(struct its_flash_fs_ctx_t *fs_ctx, 217 uint32_t idx_start, 218 uint32_t idx_end); 219 220 /** 221 * \brief Gets current scratch datablock physical ID. 222 * 223 * \param[in,out] fs_ctx Filesystem context 224 * \param[in] lblock Logical block number 225 * 226 * \return current scratch data block 227 */ 228 uint32_t its_flash_fs_mblock_cur_data_scratch_id( 229 struct its_flash_fs_ctx_t *fs_ctx, 230 uint32_t lblock); 231 232 /** 233 * \brief Gets file metadata entry index and file metadata. 234 * 235 * \note A NULL [file_meta] indicates ignoring file meta. 236 * 237 * \param[in,out] fs_ctx Filesystem context 238 * \param[in] fid ID of the file 239 * \param[out] idx Index of the file metadata in the file system 240 * \param[out] file_meta Pointer to file meta structure 241 * 242 * \return Returns error code as specified in \ref psa_status_t 243 */ 244 psa_status_t its_flash_fs_mblock_get_file_idx_meta(struct its_flash_fs_ctx_t *fs_ctx, 245 const uint8_t *fid, 246 uint32_t *idx, 247 struct its_file_meta_t *file_meta); 248 /** 249 * \brief Gets file metadata entry index of the first file with one of the 250 * provided flags set. 251 * 252 * \param[in,out] fs_ctx Filesystem context 253 * \param[in] flags Flags to search for 254 * \param[out] idx Index of the file metadata in the file system 255 * 256 * \return Returns error code as specified in \ref psa_status_t 257 */ 258 psa_status_t its_flash_fs_mblock_get_file_idx_flag( 259 struct its_flash_fs_ctx_t *fs_ctx, 260 uint32_t flags, 261 uint32_t *idx); 262 263 /** 264 * \brief Finalizes an update operation. 265 * Last step when a create/write/delete is performed. 266 * 267 * \param[in,out] fs_ctx Filesystem context 268 * 269 * \return Returns offset value in metadata block 270 */ 271 psa_status_t its_flash_fs_mblock_meta_update_finalize( 272 struct its_flash_fs_ctx_t *fs_ctx); 273 274 /** 275 * \brief Writes the files data area of logical block 0 into the scratch 276 * block. 277 * 278 * \note The files data in the logical block 0 is stored in same physical 279 * block where the metadata is stored. A change in the metadata requires a 280 * swap of physical blocks. So, the files data stored in the current 281 * medadata block needs to be copied in the scratch block, unless 282 * the data of the file processed is located in the logical block 0. 283 * 284 * \param[in,out] fs_ctx Filesystem context 285 * 286 * \return Returns error code as specified in \ref psa_status_t 287 */ 288 psa_status_t its_flash_fs_mblock_migrate_lb0_data_to_scratch( 289 struct its_flash_fs_ctx_t *fs_ctx); 290 291 /** 292 * \brief Reads specified file metadata. 293 * 294 * \param[in,out] fs_ctx Filesystem context 295 * \param[in] idx File metadata entry index 296 * \param[out] file_meta Pointer to file meta structure 297 * 298 * \return Returns error code as specified in \ref psa_status_t 299 */ 300 psa_status_t its_flash_fs_mblock_read_file_meta( 301 struct its_flash_fs_ctx_t *fs_ctx, 302 uint32_t idx, 303 struct its_file_meta_t *file_meta); 304 305 /** 306 * \brief Reads specified logical block metadata. 307 * 308 * \param[in,out] fs_ctx Filesystem context 309 * \param[in] lblock Logical block number 310 * \param[out] block_meta Pointer to block meta structure 311 * 312 * \return Returns error code as specified in \ref psa_status_t 313 */ 314 psa_status_t its_flash_fs_mblock_read_block_metadata( 315 struct its_flash_fs_ctx_t *fs_ctx, 316 uint32_t lblock, 317 struct its_block_meta_t *block_meta); 318 319 /** 320 * \brief Reads specified logical block metadata based on the backward 321 * compatible FS. 322 * 323 * \param[in,out] fs_ctx Filesystem context 324 * \param[in] lblock Logical block number 325 * \param[out] block_meta Pointer to block meta structure 326 * 327 * \return Returns error code as specified in \ref psa_status_t 328 */ 329 psa_status_t its_flash_fs_mblock_read_block_metadata_comp( 330 struct its_flash_fs_ctx_t *fs_ctx, 331 uint32_t lblock, 332 struct its_block_meta_t *block_meta); 333 334 /** 335 * \brief Reserves space for a file. 336 * 337 * \param[in,out] fs_ctx Filesystem context 338 * \param[in] fid File ID 339 * \param[in] use_spare If true then the spare file will be used, 340 * otherwise at least one file will be left free 341 * \param[in] size Size of the file for which space is reserve 342 * \param[in] flags Flags set when the file was created 343 * \param[out] file_meta_idx File metadata entry index 344 * \param[out] file_meta File metadata entry 345 * \param[out] block_meta Block metadata entry 346 * 347 * \return Returns error code as specified in \ref psa_status_t 348 */ 349 psa_status_t its_flash_fs_mblock_reserve_file( 350 struct its_flash_fs_ctx_t *fs_ctx, 351 const uint8_t *fid, 352 bool use_spare, 353 size_t size, 354 uint32_t flags, 355 uint32_t *file_meta_idx, 356 struct its_file_meta_t *file_meta, 357 struct its_block_meta_t *block_meta); 358 359 /** 360 * \brief Resets metablock by cleaning and initializing the metadatablock. 361 * 362 * \param[in,out] fs_ctx Filesystem context 363 * 364 * \return Returns value as specified in \ref psa_status_t 365 */ 366 psa_status_t its_flash_fs_mblock_reset_metablock( 367 struct its_flash_fs_ctx_t *fs_ctx); 368 369 /** 370 * \brief Sets current data scratch block 371 * 372 * \param[in,out] fs_ctx Filesystem context 373 * \param[in] phy_id Physical ID of scratch data block 374 * \param[in] lblock Logical block number 375 */ 376 void its_flash_fs_mblock_set_data_scratch(struct its_flash_fs_ctx_t *fs_ctx, 377 uint32_t phy_id, uint32_t lblock); 378 379 /** 380 * \brief Puts logical block's metadata in scratch metadata block 381 * 382 * \param[in,out] fs_ctx Filesystem context 383 * \param[in] lblock Logical block number 384 * \param[in] block_meta Pointer to block's metadata 385 * 386 * \return Returns error code as specified in \ref psa_status_t 387 */ 388 psa_status_t its_flash_fs_mblock_update_scratch_block_meta( 389 struct its_flash_fs_ctx_t *fs_ctx, 390 uint32_t lblock, 391 struct its_block_meta_t *block_meta); 392 393 /** 394 * \brief Writes a file metadata entry into scratch metadata block. 395 * 396 * \param[in,out] fs_ctx Filesystem context 397 * \param[in] idx File's index in the metadata table 398 * \param[in] file_meta Metadata pointer 399 * 400 * \return Returns error code as specified in \ref psa_status_t 401 */ 402 psa_status_t its_flash_fs_mblock_update_scratch_file_meta( 403 struct its_flash_fs_ctx_t *fs_ctx, 404 uint32_t idx, 405 const struct its_file_meta_t *file_meta); 406 407 /** 408 * \brief Moves data from source block ID to destination block ID. 409 * 410 * \param[in] fs_ctx Filesystem context 411 * \param[in] dst_block Destination block ID 412 * \param[in] dst_offset Destination offset position from the init of the 413 * destination block 414 * \param[in] src_block Source block ID 415 * \param[in] src_offset Source offset position from the init of the source 416 * block 417 * \param[in] size Number of bytes to moves 418 * 419 * \note This function assumes all input values are valid. That is, the address 420 * range, based on blockid, offset and size, is a valid range in flash. 421 * It also assumes that the destination block is already erased and ready 422 * to be written. 423 * 424 * \return Returns PSA_SUCCESS if the function is executed correctly. Otherwise, 425 * it returns PSA_ERROR_STORAGE_FAILURE. 426 */ 427 psa_status_t its_flash_fs_block_to_block_move(struct its_flash_fs_ctx_t *fs_ctx, 428 uint32_t dst_block, 429 size_t dst_offset, 430 uint32_t src_block, 431 size_t src_offset, 432 size_t size); 433 434 #ifdef __cplusplus 435 } 436 #endif 437 438 #endif /* __ITS_FLASH_FS_MBLOCK_H__ */ 439