1 /*
2  * Copyright (c) 2018-2023, Arm Limited. All rights reserved.
3  * Copyright (c) 2020, Cypress Semiconductor Corporation. All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  */
8 
9 /**
10  * \file  its_flash_fs.h
11  *
12  * \brief Internal Trusted Storage service filesystem abstraction APIs.
13  *        The purpose of this abstraction is to have the ability to plug-in
14  *        other filesystems or filesystem proxies (supplicant).
15  */
16 
17 #ifndef __ITS_FLASH_FS_H__
18 #define __ITS_FLASH_FS_H__
19 
20 #include <stddef.h>
21 #include <stdint.h>
22 
23 #include "its_flash_fs_mblock.h"
24 #include "psa/error.h"
25 
26 #ifdef __cplusplus
27 extern "C" {
28 #endif
29 
30 /* Space reserved for user-defined flags. These are stored in the file metadata
31  * and can be retrieved by getting the file info.
32  */
33 #define ITS_FLASH_FS_USER_FLAGS_MASK   ((1UL << 16) - 1)
34 
35 /* Filesystem flags that can be provided when calling the write function */
36 #define ITS_FLASH_FS_WRITE_FLAGS_MASK  ((1UL << 24) - (1UL << 16))
37 /* Create the file if it does not already exist */
38 #define ITS_FLASH_FS_FLAG_CREATE       (1UL << 16)
39 /* Remove existing file data if it exists */
40 #define ITS_FLASH_FS_FLAG_TRUNCATE     (1UL << 17)
41 
42 /* Invalid block index */
43 #define ITS_BLOCK_INVALID_ID 0xFFFFFFFFU
44 
45 /**
46  * \struct its_flash_fs_config_t
47  *
48  * \brief Structure containing the flash filesystem configuration parameters.
49  */
50 struct its_flash_fs_config_t {
51     const void *flash_dev;    /**< Pointer to the flash device */
52     uint32_t flash_area_addr; /**< Base address of the flash region */
53     uint32_t sector_size;     /**< Size of the flash device's physical erase
54                                *   unit
55                                */
56     uint32_t block_size;      /**< Size of a logical filesystem erase unit, a
57                                *   multiple of sector_size.
58                                */
59     uint16_t num_blocks;      /**< Number of logical erase blocks */
60     uint16_t program_unit;    /**< Minimum size of a program operation */
61     uint16_t max_file_size;   /**< Maximum file size */
62     uint16_t max_num_files;   /**< Maximum number of files */
63     uint8_t erase_val;        /**< Value of a byte after erase (usually 0xFF) */
64 };
65 
66 /**
67  * \struct its_flash_fs_ops_t
68  *
69  * \brief Structure containing the filesystem flash operation parameters.
70  */
71 struct its_flash_fs_ops_t {
72     /**
73      * \brief Initializes the flash device.
74      *
75      * \param[in] cfg  Filesystem configuration
76      *
77      * \return Returns PSA_SUCCESS if the function is executed correctly.
78      *         Otherwise, it returns PSA_ERROR_STORAGE_FAILURE.
79      */
80     psa_status_t (*init)(const struct its_flash_fs_config_t *cfg);
81 
82     /**
83      * \brief Reads block data from the position specified by block ID and
84      *        offset.
85      *
86      * \param[in]  cfg       Filesystem configuration
87      * \param[in]  block_id  Block ID
88      * \param[out] buf       Buffer pointer to store the data read
89      * \param[in]  offset    Offset position from the init of the block
90      * \param[in]  size      Number of bytes to read
91      *
92      * \note This function assumes all input values are valid. That is, the
93      *       address range, based on block_id, offset and size, is a valid range
94      *       in flash.
95      *
96      * \return Returns PSA_SUCCESS if the function is executed correctly.
97      *         Otherwise, it returns PSA_ERROR_STORAGE_FAILURE.
98      */
99     psa_status_t (*read)(const struct its_flash_fs_config_t *cfg,
100                          uint32_t block_id, uint8_t *buf, size_t offset,
101                          size_t size);
102 
103     /**
104      * \brief Writes block data to the position specified by block ID and
105      *        offset.
106      *
107      * \param[in] cfg       Filesystem configuration
108      * \param[in] block_id  Block ID
109      * \param[in] buf       Buffer pointer to the write data
110      * \param[in] offset    Offset position from the init of the block
111      * \param[in] size      Number of bytes to write
112      *
113      * \note This function assumes all input values are valid. That is, the
114      *       address range, based on block_id, offset and size, is a valid range
115      *       in flash.
116      *
117      * \return Returns PSA_SUCCESS if the function is executed correctly.
118      *         Otherwise, it returns PSA_ERROR_STORAGE_FAILURE.
119      */
120     psa_status_t (*write)(const struct its_flash_fs_config_t *cfg,
121                           uint32_t block_id, const uint8_t *buf, size_t offset,
122                           size_t size);
123 
124     /**
125      * \brief Flushes modifications to a block to flash. Must be called after a
126      *        sequence of calls to write() (including via
127      *        its_flash_block_to_block_move()) for one block ID, before any call
128      *        to the same functions for a different block ID.
129      *
130      * \param[in] cfg  Filesystem configuration
131      *
132      * \param[in] block_id  Block ID
133      *
134      * \note It is permitted for write() to commit block updates immediately, in
135      *       which case this function is a no-op.
136      *
137      * \return Returns PSA_SUCCESS if the function is executed correctly.
138      *         Otherwise, it returns PSA_ERROR_STORAGE_FAILURE.
139      */
140     psa_status_t (*flush)(const struct its_flash_fs_config_t *cfg,
141                           uint32_t block_id);
142 
143     /**
144      * \brief Erases block ID data.
145      *
146      * \param[in] cfg       Filesystem configuration
147      * \param[in] block_id  Block ID
148      *
149      * \note This function assumes the input value is valid.
150      *
151      * \return Returns PSA_SUCCESS if the function is executed correctly.
152      *         Otherwise, it returns PSA_ERROR_STORAGE_FAILURE.
153      */
154     psa_status_t (*erase)(const struct its_flash_fs_config_t *cfg,
155                           uint32_t block_id);
156 };
157 
158 /**
159  * \brief ITS flash filesystem context type, used to maintain state across FS
160  *        operations.
161  *
162  * \details The user should allocate a variable of this type, initialised to
163  *          zero, before calling its_flash_fs_prepare, and then pass it to each
164  *          subsequent FS operation. The contents are internal to the
165  *          filesystem.
166  */
167 typedef struct its_flash_fs_ctx_t its_flash_fs_ctx_t;
168 
169 /*!
170  * \struct its_flash_fs_file_info_t
171  *
172  * \brief Structure containing file information.
173  *
174  * \details This structure is not written to the filesystem, it is used by the
175  *          file system functions to simplify accessing the containing
176  *          information.
177  */
178 struct its_flash_fs_file_info_t {
179     size_t size_current;  /*!< The current size of the file in bytes */
180     size_t size_max;      /*!< The maximum size of the file in bytes. */
181     uint32_t flags;       /*!< Flags set when the file was created */
182 #ifdef ITS_ENCRYPTION
183     /*!< Additional authenticated data */
184     uint8_t add[ITS_FILE_ID_SIZE + ITS_DATA_SIZE_FIELD_SIZE + ITS_FLAG_SIZE];
185     uint8_t nonce[12];/*!< Nonce/IV for encrypted files */
186     uint8_t tag[16];   /*!< Authentication tag */
187 #endif
188 };
189 
190 /**
191  * \brief Initialises the filesystem context. Must be called successfully before
192  *        any other filesystem API is called.
193  *
194  * \param[in,out] fs_ctx  Filesystem context to initialise. Must have been
195  *                        allocated by the caller.
196  * \param[in]     fs_cfg  Filesystem configuration to associate with the
197  *                        context.
198  * \param[in]     fs_ops  Filesystem flash operations to associate with the
199  *                        context.
200  *
201  * \return Returns error code as specified in \ref psa_status_t
202  */
203 psa_status_t its_flash_fs_init_ctx(its_flash_fs_ctx_t *fs_ctx,
204                                    const struct its_flash_fs_config_t *fs_cfg,
205                                    const struct its_flash_fs_ops_t *fs_ops);
206 
207 /**
208  * \brief Prepares the filesystem to accept operations on the files.
209  *
210  * \param[in,out] fs_ctx  Filesystem context to prepare. Must have been
211  *                        initialised by its_flash_fs_init_ctx().
212  *
213  * \return Returns error code as specified in \ref psa_status_t
214  */
215 psa_status_t its_flash_fs_prepare(its_flash_fs_ctx_t *fs_ctx);
216 
217 /**
218  * \brief Wipes all files from the filesystem.
219  *
220  * \param[in,out] fs_ctx  Filesystem context to wipe. Must be prepared again
221  *                        before further use.
222  *
223  * \return Returns error code as specified in \ref psa_status_t
224  */
225 psa_status_t its_flash_fs_wipe_all(its_flash_fs_ctx_t *fs_ctx);
226 
227 /**
228  * \brief Gets the file information referenced by the file ID.
229  *
230  * \param[in,out] fs_ctx  Filesystem context
231  * \param[in]     fid     File ID
232  * \param[out]    info    Pointer to the file information
233  *                        structure \ref its_flash_fs_file_info_t
234  *
235  * \return Returns error code specified in \ref psa_status_t
236  */
237 psa_status_t its_flash_fs_file_get_info(its_flash_fs_ctx_t *fs_ctx,
238                                         const uint8_t *fid,
239                                         struct its_flash_fs_file_info_t *info);
240 
241 /**
242  * \brief Writes data to a file.
243  *
244  * \param[in,out] fs_ctx     Filesystem context
245  * \param[in]     fid        File ID
246  * \param[in]     finfo      Pointer to \ref its_flash_fs_file_info_t
247  * \param[in]     data_size  Size of the incoming write data.
248  * \param[in]     offset     Offset in the file to write. Must be less than or
249  *                           equal to the current file size.
250  * \param[in]     data       Pointer to buffer containing data to be written
251  *
252  * \return Returns error code as specified in \ref psa_status_t
253  */
254 psa_status_t its_flash_fs_file_write(its_flash_fs_ctx_t *fs_ctx,
255                                      const uint8_t *fid,
256                                      struct its_flash_fs_file_info_t *finfo,
257                                      size_t data_size,
258                                      size_t offset,
259                                      const uint8_t *data);
260 
261 /**
262  * \brief Reads data from an existing file.
263  *
264  * \param[in,out] fs_ctx  Filesystem context
265  * \param[in]     fid     File ID
266  * \param[in]     size    Size to be read
267  * \param[in]     offset  Offset in the file
268  * \param[out]    data    Pointer to buffer to store the data
269  *
270  * \return Returns error code as specified in \ref psa_status_t
271  */
272 psa_status_t its_flash_fs_file_read(its_flash_fs_ctx_t *fs_ctx,
273                                     const uint8_t *fid,
274                                     size_t size,
275                                     size_t offset,
276                                     uint8_t *data);
277 
278 /**
279  * \brief Deletes file referenced by the file ID.
280  *
281  * \param[in,out] fs_ctx  Filesystem context
282  * \param[in]     fid     File ID
283  *
284  * \return Returns error code as specified in \ref psa_status_t
285  */
286 psa_status_t its_flash_fs_file_delete(its_flash_fs_ctx_t *fs_ctx,
287                                       const uint8_t *fid);
288 
289 #ifdef __cplusplus
290 }
291 #endif
292 
293 #endif /* __ITS_FLASH_FS_H__ */
294