Merge pull request #1331 from Guilhem7/master
[RRG-proxmark3.git] / armsrc / spiffs_nucleus.h
blob7fbf98acf53e1bca43436433cc8663d328730336
1 /*
2 * spiffs_nucleus.h
4 * Created on: Jun 15, 2013
5 * Author: petera
6 */
8 /* SPIFFS layout
10 * spiffs is designed for following spi flash characteristics:
11 * - only big areas of data (blocks) can be erased
12 * - erasing resets all bits in a block to ones
13 * - writing pulls ones to zeroes
14 * - zeroes cannot be pulled to ones, without erase
15 * - wear leveling
17 * spiffs is also meant to be run on embedded, memory constraint devices.
19 * Entire area is divided in blocks. Entire area is also divided in pages.
20 * Each block contains same number of pages. A page cannot be erased, but a
21 * block can be erased.
23 * Entire area must be block_size * x
24 * page_size must be block_size / (2^y) where y > 2
26 * ex: area = 1024*1024 bytes, block size = 65536 bytes, page size = 256 bytes
28 * BLOCK 0 PAGE 0 object lookup 1
29 * PAGE 1 object lookup 2
30 * ...
31 * PAGE n-1 object lookup n
32 * PAGE n object data 1
33 * PAGE n+1 object data 2
34 * ...
35 * PAGE n+m-1 object data m
37 * BLOCK 1 PAGE n+m object lookup 1
38 * PAGE n+m+1 object lookup 2
39 * ...
40 * PAGE 2n+m-1 object lookup n
41 * PAGE 2n+m object data 1
42 * PAGE 2n+m object data 2
43 * ...
44 * PAGE 2n+2m-1 object data m
45 * ...
47 * n is number of object lookup pages, which is number of pages needed to index all pages
48 * in a block by object id
49 * : block_size / page_size * sizeof(obj_id) / page_size
50 * m is number data pages, which is number of pages in block minus number of lookup pages
51 * : block_size / page_size - block_size / page_size * sizeof(obj_id) / page_size
52 * thus, n+m is total number of pages in a block
53 * : block_size / page_size
55 * ex: n = 65536/256*2/256 = 2, m = 65536/256 - 2 = 254 => n+m = 65536/256 = 256
57 * Object lookup pages contain object id entries. Each entry represent the corresponding
58 * data page.
59 * Assuming a 16 bit object id, an object id being 0xffff represents a free page.
60 * An object id being 0x0000 represents a deleted page.
62 * ex: page 0 : lookup : 0008 0001 0aaa ffff ffff ffff ffff ffff ..
63 * page 1 : lookup : ffff ffff ffff ffff ffff ffff ffff ffff ..
64 * page 2 : data : data for object id 0008
65 * page 3 : data : data for object id 0001
66 * page 4 : data : data for object id 0aaa
67 * ...
70 * Object data pages can be either object index pages or object content.
71 * All object data pages contains a data page header, containing object id and span index.
72 * The span index denotes the object page ordering amongst data pages with same object id.
73 * This applies to both object index pages (when index spans more than one page of entries),
74 * and object data pages.
75 * An object index page contains page entries pointing to object content page. The entry index
76 * in a object index page correlates to the span index in the actual object data page.
77 * The first object index page (span index 0) is called object index header page, and also
78 * contains object flags (directory/file), size, object name etc.
80 * ex:
81 * BLOCK 1
82 * PAGE 256: objectl lookup page 1
83 * [*123] [ 123] [ 123] [ 123]
84 * [ 123] [*123] [ 123] [ 123]
85 * [free] [free] [free] [free] ...
86 * PAGE 257: objectl lookup page 2
87 * [free] [free] [free] [free] ...
88 * PAGE 258: object index page (header)
89 * obj.id:0123 span.ix:0000 flags:INDEX
90 * size:1600 name:ex.txt type:file
91 * [259] [260] [261] [262]
92 * PAGE 259: object data page
93 * obj.id:0123 span.ix:0000 flags:DATA
94 * PAGE 260: object data page
95 * obj.id:0123 span.ix:0001 flags:DATA
96 * PAGE 261: object data page
97 * obj.id:0123 span.ix:0002 flags:DATA
98 * PAGE 262: object data page
99 * obj.id:0123 span.ix:0003 flags:DATA
100 * PAGE 263: object index page
101 * obj.id:0123 span.ix:0001 flags:INDEX
102 * [264] [265] [fre] [fre]
103 * [fre] [fre] [fre] [fre]
104 * PAGE 264: object data page
105 * obj.id:0123 span.ix:0004 flags:DATA
106 * PAGE 265: object data page
107 * obj.id:0123 span.ix:0005 flags:DATA
110 #ifndef SPIFFS_NUCLEUS_H_
111 #define SPIFFS_NUCLEUS_H_
113 #include "common.h"
115 #include "string.h"
116 #include "spiffs.h"
118 #define _SPIFFS_ERR_CHECK_FIRST (SPIFFS_ERR_INTERNAL - 1)
119 #define SPIFFS_ERR_CHECK_OBJ_ID_MISM (SPIFFS_ERR_INTERNAL - 1)
120 #define SPIFFS_ERR_CHECK_SPIX_MISM (SPIFFS_ERR_INTERNAL - 2)
121 #define SPIFFS_ERR_CHECK_FLAGS_BAD (SPIFFS_ERR_INTERNAL - 3)
122 #define _SPIFFS_ERR_CHECK_LAST (SPIFFS_ERR_INTERNAL - 4)
124 // visitor result, continue searching
125 #define SPIFFS_VIS_COUNTINUE (SPIFFS_ERR_INTERNAL - 20)
126 // visitor result, continue searching after reloading lu buffer
127 #define SPIFFS_VIS_COUNTINUE_RELOAD (SPIFFS_ERR_INTERNAL - 21)
128 // visitor result, stop searching
129 #define SPIFFS_VIS_END (SPIFFS_ERR_INTERNAL - 22)
131 // updating an object index contents
132 #define SPIFFS_EV_IX_UPD (0)
133 // creating a new object index
134 #define SPIFFS_EV_IX_NEW (1)
135 // deleting an object index
136 #define SPIFFS_EV_IX_DEL (2)
137 // moving an object index without updating contents
138 #define SPIFFS_EV_IX_MOV (3)
139 // updating an object index header data only, not the table itself
140 #define SPIFFS_EV_IX_UPD_HDR (4)
142 #define SPIFFS_OBJ_ID_IX_FLAG ((spiffs_obj_id)(1<<(8*sizeof(spiffs_obj_id)-1)))
144 #define SPIFFS_UNDEFINED_LEN (u32_t)(-1)
146 #define SPIFFS_OBJ_ID_DELETED ((spiffs_obj_id)0)
147 #define SPIFFS_OBJ_ID_FREE ((spiffs_obj_id)-1)
151 #if defined(__GNUC__) || defined(__clang__) || defined(__TI_COMPILER_VERSION__)
152 /* For GCC, clang and TI compilers */
153 #define SPIFFS_PACKED __attribute__((packed))
154 #elif defined(__ICCARM__) || defined(__CC_ARM)
155 /* For IAR ARM and Keil MDK-ARM compilers */
156 #define SPIFFS_PACKED
158 #else
159 /* Unknown compiler */
160 #define SPIFFS_PACKED
161 #endif
165 #if SPIFFS_USE_MAGIC
166 #if !SPIFFS_USE_MAGIC_LENGTH
167 #define SPIFFS_MAGIC(fs, bix) \
168 ((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs)))
169 #else // SPIFFS_USE_MAGIC_LENGTH
170 #define SPIFFS_MAGIC(fs, bix) \
171 ((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs) ^ ((fs)->block_count - (bix))))
172 #endif // SPIFFS_USE_MAGIC_LENGTH
173 #endif // SPIFFS_USE_MAGIC
175 #define SPIFFS_CONFIG_MAGIC (0x20090315)
177 #if SPIFFS_SINGLETON == 0
178 #define SPIFFS_CFG_LOG_PAGE_SZ(fs) \
179 ((fs)->cfg.log_page_size)
180 #define SPIFFS_CFG_LOG_BLOCK_SZ(fs) \
181 ((fs)->cfg.log_block_size)
182 #define SPIFFS_CFG_PHYS_SZ(fs) \
183 ((fs)->cfg.phys_size)
184 #define SPIFFS_CFG_PHYS_ERASE_SZ(fs) \
185 ((fs)->cfg.phys_erase_block)
186 #define SPIFFS_CFG_PHYS_ADDR(fs) \
187 ((fs)->cfg.phys_addr)
188 #endif
190 // total number of pages
191 #define SPIFFS_MAX_PAGES(fs) \
192 ( SPIFFS_CFG_PHYS_SZ(fs)/SPIFFS_CFG_LOG_PAGE_SZ(fs) )
193 // total number of pages per block, including object lookup pages
194 #define SPIFFS_PAGES_PER_BLOCK(fs) \
195 ( SPIFFS_CFG_LOG_BLOCK_SZ(fs)/SPIFFS_CFG_LOG_PAGE_SZ(fs) )
196 // number of object lookup pages per block
197 #define SPIFFS_OBJ_LOOKUP_PAGES(fs) \
198 (MAX(1, (SPIFFS_PAGES_PER_BLOCK(fs) * sizeof(spiffs_obj_id)) / SPIFFS_CFG_LOG_PAGE_SZ(fs)) )
199 // checks if page index belongs to object lookup
200 #define SPIFFS_IS_LOOKUP_PAGE(fs,pix) \
201 (((pix) % SPIFFS_PAGES_PER_BLOCK(fs)) < SPIFFS_OBJ_LOOKUP_PAGES(fs))
202 // number of object lookup entries in all object lookup pages
203 #define SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs) \
204 (SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs))
205 // converts a block to physical address
206 #define SPIFFS_BLOCK_TO_PADDR(fs, block) \
207 ( SPIFFS_CFG_PHYS_ADDR(fs) + (block)* SPIFFS_CFG_LOG_BLOCK_SZ(fs) )
208 // converts a object lookup entry to page index
209 #define SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, block, entry) \
210 ((block)*SPIFFS_PAGES_PER_BLOCK(fs) + (SPIFFS_OBJ_LOOKUP_PAGES(fs) + entry))
211 // converts a object lookup entry to physical address of corresponding page
212 #define SPIFFS_OBJ_LOOKUP_ENTRY_TO_PADDR(fs, block, entry) \
213 (SPIFFS_BLOCK_TO_PADDR(fs, block) + (SPIFFS_OBJ_LOOKUP_PAGES(fs) + entry) * SPIFFS_CFG_LOG_PAGE_SZ(fs) )
214 // converts a page to physical address
215 #define SPIFFS_PAGE_TO_PADDR(fs, page) \
216 ( SPIFFS_CFG_PHYS_ADDR(fs) + (page) * SPIFFS_CFG_LOG_PAGE_SZ(fs) )
217 // converts a physical address to page
218 #define SPIFFS_PADDR_TO_PAGE(fs, addr) \
219 ( ((addr) - SPIFFS_CFG_PHYS_ADDR(fs)) / SPIFFS_CFG_LOG_PAGE_SZ(fs) )
220 // gives index in page for a physical address
221 #define SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr) \
222 ( ((addr) - SPIFFS_CFG_PHYS_ADDR(fs)) % SPIFFS_CFG_LOG_PAGE_SZ(fs) )
223 // returns containing block for given page
224 #define SPIFFS_BLOCK_FOR_PAGE(fs, page) \
225 ( (page) / SPIFFS_PAGES_PER_BLOCK(fs) )
226 // returns starting page for block
227 #define SPIFFS_PAGE_FOR_BLOCK(fs, block) \
228 ( (block) * SPIFFS_PAGES_PER_BLOCK(fs) )
229 // converts page to entry in object lookup page
230 #define SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, page) \
231 ( (page) % SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs) )
232 // returns data size in a data page
233 #define SPIFFS_DATA_PAGE_SIZE(fs) \
234 ( SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_header) )
235 // returns physical address for block's erase count,
236 // always in the physical last entry of the last object lookup page
237 #define SPIFFS_ERASE_COUNT_PADDR(fs, bix) \
238 ( SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_OBJ_LOOKUP_PAGES(fs) * SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_obj_id) )
239 // returns physical address for block's magic,
240 // always in the physical second last entry of the last object lookup page
241 #define SPIFFS_MAGIC_PADDR(fs, bix) \
242 ( SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_OBJ_LOOKUP_PAGES(fs) * SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_obj_id)*2 )
243 // checks if there is any room for magic in the object luts
244 #define SPIFFS_CHECK_MAGIC_POSSIBLE(fs) \
245 ( (SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs) % (SPIFFS_CFG_LOG_PAGE_SZ(fs)/sizeof(spiffs_obj_id))) * sizeof(spiffs_obj_id) \
246 <= (SPIFFS_CFG_LOG_PAGE_SZ(fs)-sizeof(spiffs_obj_id)*2) )
248 // define helpers object
250 // entries in an object header page index
251 #define SPIFFS_OBJ_HDR_IX_LEN(fs) \
252 ((SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_object_ix_header))/sizeof(spiffs_page_ix))
253 // entries in an object page index
254 #define SPIFFS_OBJ_IX_LEN(fs) \
255 ((SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_object_ix))/sizeof(spiffs_page_ix))
256 // object index entry for given data span index
257 #define SPIFFS_OBJ_IX_ENTRY(fs, spix) \
258 ((spix) < SPIFFS_OBJ_HDR_IX_LEN(fs) ? (spix) : (((spix)-SPIFFS_OBJ_HDR_IX_LEN(fs))%SPIFFS_OBJ_IX_LEN(fs)))
259 // object index span index number for given data span index or entry
260 #define SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, spix) \
261 ((spix) < SPIFFS_OBJ_HDR_IX_LEN(fs) ? 0 : (1+((spix)-SPIFFS_OBJ_HDR_IX_LEN(fs))/SPIFFS_OBJ_IX_LEN(fs)))
262 // get data span index for object index span index
263 #define SPIFFS_DATA_SPAN_IX_FOR_OBJ_IX_SPAN_IX(fs, spix) \
264 ( (spix) == 0 ? 0 : (SPIFFS_OBJ_HDR_IX_LEN(fs) + (((spix)-1) * SPIFFS_OBJ_IX_LEN(fs))) )
266 #if SPIFFS_FILEHDL_OFFSET
267 #define SPIFFS_FH_OFFS(fs, fh) ((fh) != 0 ? ((fh) + (fs)->cfg.fh_ix_offset) : 0)
268 #define SPIFFS_FH_UNOFFS(fs, fh) ((fh) != 0 ? ((fh) - (fs)->cfg.fh_ix_offset) : 0)
269 #else
270 #define SPIFFS_FH_OFFS(fs, fh) (fh)
271 #define SPIFFS_FH_UNOFFS(fs, fh) (fh)
272 #endif
275 #define SPIFFS_OP_T_OBJ_LU (0<<0)
276 #define SPIFFS_OP_T_OBJ_LU2 (1<<0)
277 #define SPIFFS_OP_T_OBJ_IX (2<<0)
278 #define SPIFFS_OP_T_OBJ_DA (3<<0)
279 #define SPIFFS_OP_C_DELE (0<<2)
280 #define SPIFFS_OP_C_UPDT (1<<2)
281 #define SPIFFS_OP_C_MOVS (2<<2)
282 #define SPIFFS_OP_C_MOVD (3<<2)
283 #define SPIFFS_OP_C_FLSH (4<<2)
284 #define SPIFFS_OP_C_READ (5<<2)
285 #define SPIFFS_OP_C_WRTHRU (6<<2)
287 #define SPIFFS_OP_TYPE_MASK (3<<0)
288 #define SPIFFS_OP_COM_MASK (7<<2)
291 // if 0, this page is written to, else clean
292 #define SPIFFS_PH_FLAG_USED (1<<0)
293 // if 0, writing is finalized, else under modification
294 #define SPIFFS_PH_FLAG_FINAL (1<<1)
295 // if 0, this is an index page, else a data page
296 #define SPIFFS_PH_FLAG_INDEX (1<<2)
297 // if 0, page is deleted, else valid
298 #define SPIFFS_PH_FLAG_DELET (1<<7)
299 // if 0, this index header is being deleted
300 #define SPIFFS_PH_FLAG_IXDELE (1<<6)
303 #define SPIFFS_CHECK_MOUNT(fs) \
304 ((fs)->mounted != 0)
306 #define SPIFFS_CHECK_CFG(fs) \
307 ((fs)->config_magic == SPIFFS_CONFIG_MAGIC)
309 #define SPIFFS_CHECK_RES(res) \
310 do { \
311 if ((res) < SPIFFS_OK) return (res); \
312 } while (0);
314 #define SPIFFS_API_CHECK_MOUNT(fs) \
315 if (!SPIFFS_CHECK_MOUNT((fs))) { \
316 (fs)->err_code = SPIFFS_ERR_NOT_MOUNTED; \
317 return SPIFFS_ERR_NOT_MOUNTED; \
320 #define SPIFFS_API_CHECK_CFG(fs) \
321 if (!SPIFFS_CHECK_CFG((fs))) { \
322 (fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED; \
323 return SPIFFS_ERR_NOT_CONFIGURED; \
326 #define SPIFFS_API_CHECK_RES(fs, res) \
327 if ((res) < SPIFFS_OK) { \
328 (fs)->err_code = (res); \
329 return (res); \
332 #define SPIFFS_API_CHECK_RES_UNLOCK(fs, res) \
333 if ((res) < SPIFFS_OK) { \
334 (fs)->err_code = (res); \
335 SPIFFS_UNLOCK(fs); \
336 return (res); \
339 #define SPIFFS_VALIDATE_OBJIX(ph, objid, spix) \
340 if (((ph).flags & SPIFFS_PH_FLAG_USED) != 0) return SPIFFS_ERR_IS_FREE; \
341 if (((ph).flags & SPIFFS_PH_FLAG_DELET) == 0) return SPIFFS_ERR_DELETED; \
342 if (((ph).flags & SPIFFS_PH_FLAG_FINAL) != 0) return SPIFFS_ERR_NOT_FINALIZED; \
343 if (((ph).flags & SPIFFS_PH_FLAG_INDEX) != 0) return SPIFFS_ERR_NOT_INDEX; \
344 if (((objid) & SPIFFS_OBJ_ID_IX_FLAG) == 0) return SPIFFS_ERR_NOT_INDEX; \
345 if ((ph).span_ix != (spix)) return SPIFFS_ERR_INDEX_SPAN_MISMATCH;
346 //if ((spix) == 0 && ((ph).flags & SPIFFS_PH_FLAG_IXDELE) == 0) return SPIFFS_ERR_DELETED;
348 #define SPIFFS_VALIDATE_DATA(ph, objid, spix) \
349 if (((ph).flags & SPIFFS_PH_FLAG_USED) != 0) return SPIFFS_ERR_IS_FREE; \
350 if (((ph).flags & SPIFFS_PH_FLAG_DELET) == 0) return SPIFFS_ERR_DELETED; \
351 if (((ph).flags & SPIFFS_PH_FLAG_FINAL) != 0) return SPIFFS_ERR_NOT_FINALIZED; \
352 if (((ph).flags & SPIFFS_PH_FLAG_INDEX) == 0) return SPIFFS_ERR_IS_INDEX; \
353 if ((objid) & SPIFFS_OBJ_ID_IX_FLAG) return SPIFFS_ERR_IS_INDEX; \
354 if ((ph).span_ix != (spix)) return SPIFFS_ERR_DATA_SPAN_MISMATCH;
357 // check id, only visit matching objec ids
358 #define SPIFFS_VIS_CHECK_ID (1<<0)
359 // report argument object id to visitor - else object lookup id is reported
360 #define SPIFFS_VIS_CHECK_PH (1<<1)
361 // stop searching at end of all look up pages
362 #define SPIFFS_VIS_NO_WRAP (1<<2)
364 #if SPIFFS_HAL_CALLBACK_EXTRA
366 #define SPIFFS_HAL_WRITE(_fs, _paddr, _len, _src) \
367 (_fs)->cfg.hal_write_f((_fs), (_paddr), (_len), (_src))
368 #define SPIFFS_HAL_READ(_fs, _paddr, _len, _dst) \
369 (_fs)->cfg.hal_read_f((_fs), (_paddr), (_len), (_dst))
370 #define SPIFFS_HAL_ERASE(_fs, _paddr, _len) \
371 (_fs)->cfg.hal_erase_f((_fs), (_paddr), (_len))
373 #else // SPIFFS_HAL_CALLBACK_EXTRA
375 #define SPIFFS_HAL_WRITE(_fs, _paddr, _len, _src) \
376 (_fs)->cfg.hal_write_f((_paddr), (_len), (_src))
377 #define SPIFFS_HAL_READ(_fs, _paddr, _len, _dst) \
378 (_fs)->cfg.hal_read_f((_paddr), (_len), (_dst))
379 #define SPIFFS_HAL_ERASE(_fs, _paddr, _len) \
380 (_fs)->cfg.hal_erase_f((_paddr), (_len))
382 #endif // SPIFFS_HAL_CALLBACK_EXTRA
384 #if SPIFFS_CACHE
386 #define SPIFFS_CACHE_FLAG_DIRTY (1<<0)
387 #define SPIFFS_CACHE_FLAG_WRTHRU (1<<1)
388 #define SPIFFS_CACHE_FLAG_OBJLU (1<<2)
389 #define SPIFFS_CACHE_FLAG_OBJIX (1<<3)
390 #define SPIFFS_CACHE_FLAG_DATA (1<<4)
391 #define SPIFFS_CACHE_FLAG_TYPE_WR (1<<7)
393 #define SPIFFS_CACHE_PAGE_SIZE(fs) \
394 (sizeof(spiffs_cache_page) + SPIFFS_CFG_LOG_PAGE_SZ(fs))
396 #define spiffs_get_cache(fs) \
397 ((spiffs_cache *)((fs)->cache))
399 #define spiffs_get_cache_page_hdr(fs, c, ix) \
400 ((spiffs_cache_page *)(&((c)->cpages[(ix) * SPIFFS_CACHE_PAGE_SIZE(fs)])))
402 #define spiffs_get_cache_page(fs, c, ix) \
403 ((u8_t *)(&((c)->cpages[(ix) * SPIFFS_CACHE_PAGE_SIZE(fs)])) + sizeof(spiffs_cache_page))
405 // cache page struct
406 typedef struct {
407 // cache flags
408 u8_t flags;
409 // cache page index
410 u8_t ix;
411 // last access of this cache page
412 u32_t last_access;
413 union {
414 // type read cache
415 struct spix {
416 // read cache page index
417 spiffs_page_ix pix;
418 } spix;
419 #if SPIFFS_CACHE_WR
420 // type write cache
421 struct swrc {
422 // write cache
423 spiffs_obj_id obj_id;
424 // offset in cache page
425 u32_t offset;
426 // size of cache page
427 u16_t size;
428 } swrc;
429 #endif
430 } ucache;
431 } spiffs_cache_page;
433 // cache struct
434 typedef struct {
435 u8_t cpage_count;
436 u32_t last_access;
437 u32_t cpage_use_map;
438 u32_t cpage_use_mask;
439 u8_t *cpages;
440 } spiffs_cache;
442 #endif
445 // spiffs nucleus file descriptor
446 typedef struct {
447 // the filesystem of this descriptor
448 spiffs *fs;
449 // number of file descriptor - if 0, the file descriptor is closed
450 spiffs_file file_nbr;
451 // object id - if SPIFFS_OBJ_ID_ERASED, the file was deleted
452 spiffs_obj_id obj_id;
453 // size of the file
454 u32_t size;
455 // cached object index header page index
456 spiffs_page_ix objix_hdr_pix;
457 // cached offset object index page index
458 spiffs_page_ix cursor_objix_pix;
459 // cached offset object index span index
460 spiffs_span_ix cursor_objix_spix;
461 // current absolute offset
462 u32_t offset;
463 // current file descriptor offset (cached)
464 u32_t fdoffset;
465 // fd flags
466 spiffs_flags flags;
467 #if SPIFFS_CACHE_WR
468 spiffs_cache_page *cache_page;
469 #endif
470 #if SPIFFS_TEMPORAL_FD_CACHE
471 // djb2 hash of filename
472 u32_t name_hash;
473 // hit score (score == 0 indicates never used fd)
474 u16_t score;
475 #endif
476 #if SPIFFS_IX_MAP
477 // spiffs index map, if 0 it means unmapped
478 spiffs_ix_map *ix_map;
479 #endif
480 } spiffs_fd;
483 // object structs
485 // page header, part of each page except object lookup pages
486 // NB: this is always aligned when the data page is an object index,
487 // as in this case struct spiffs_page_object_ix is used
488 typedef struct SPIFFS_PACKED {
489 // object id
490 spiffs_obj_id obj_id;
491 // object span index
492 spiffs_span_ix span_ix;
493 // flags
494 u8_t flags;
495 } spiffs_page_header;
497 // object index header page header
498 typedef struct SPIFFS_PACKED
499 #if SPIFFS_ALIGNED_OBJECT_INDEX_TABLES
500 __attribute((aligned(sizeof(spiffs_page_ix))))
501 #endif
503 // common page header
504 spiffs_page_header p_hdr;
505 // alignment
506 u8_t _align[4 - ((sizeof(spiffs_page_header) & 3) == 0 ? 4 : (sizeof(spiffs_page_header) & 3))];
507 // size of object
508 u32_t size;
509 // type of object
510 spiffs_obj_type type;
511 // name of object
512 u8_t name[SPIFFS_OBJ_NAME_LEN];
513 #if SPIFFS_OBJ_META_LEN
514 // metadata. not interpreted by SPIFFS in any way.
515 u8_t meta[SPIFFS_OBJ_META_LEN];
516 #endif
518 spiffs_page_object_ix_header;
520 // object index page header
521 typedef struct SPIFFS_PACKED {
522 spiffs_page_header p_hdr;
523 u8_t _align[4 - ((sizeof(spiffs_page_header) & 3) == 0 ? 4 : (sizeof(spiffs_page_header) & 3))];
524 } spiffs_page_object_ix;
526 // callback func for object lookup visitor
527 typedef s32_t (*spiffs_visitor_f)(spiffs *fs, spiffs_obj_id id, spiffs_block_ix bix, int ix_entry,
528 const void *user_const_p, void *user_var_p);
531 #if SPIFFS_CACHE
532 #define _spiffs_rd(fs, op, fh, addr, len, dst) \
533 spiffs_phys_rd((fs), (op), (fh), (addr), (len), (dst))
534 #define _spiffs_wr(fs, op, fh, addr, len, src) \
535 spiffs_phys_wr((fs), (op), (fh), (addr), (len), (src))
536 #else
537 #define _spiffs_rd(fs, op, fh, addr, len, dst) \
538 spiffs_phys_rd((fs), (addr), (len), (dst))
539 #define _spiffs_wr(fs, op, fh, addr, len, src) \
540 spiffs_phys_wr((fs), (addr), (len), (src))
541 #endif
543 #ifndef MIN
544 #define MIN(a,b) ((a) < (b) ? (a) : (b))
545 #endif
546 #ifndef MAX
547 #define MAX(a,b) ((a) > (b) ? (a) : (b))
548 #endif
550 // ---------------
552 s32_t spiffs_phys_rd(
553 spiffs *fs,
554 #if SPIFFS_CACHE
555 u8_t op,
556 spiffs_file fh,
557 #endif
558 u32_t addr,
559 u32_t len,
560 u8_t *dst);
562 s32_t spiffs_phys_wr(
563 spiffs *fs,
564 #if SPIFFS_CACHE
565 u8_t op,
566 spiffs_file fh,
567 #endif
568 u32_t addr,
569 u32_t len,
570 u8_t *src);
572 s32_t spiffs_phys_cpy(
573 spiffs *fs,
574 spiffs_file fh,
575 u32_t dst,
576 u32_t src,
577 u32_t len);
579 s32_t spiffs_phys_count_free_blocks(
580 spiffs *fs);
582 s32_t spiffs_obj_lu_find_entry_visitor(
583 spiffs *fs,
584 spiffs_block_ix starting_block,
585 int starting_lu_entry,
586 u8_t flags,
587 spiffs_obj_id obj_id,
588 spiffs_visitor_f v,
589 const void *user_const_p,
590 void *user_var_p,
591 spiffs_block_ix *block_ix,
592 int *lu_entry);
594 s32_t spiffs_erase_block(
595 spiffs *fs,
596 spiffs_block_ix bix);
598 #if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
599 s32_t spiffs_probe(
600 spiffs_config *cfg);
601 #endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
603 // ---------------
605 s32_t spiffs_obj_lu_scan(
606 spiffs *fs);
608 s32_t spiffs_obj_lu_find_free_obj_id(
609 spiffs *fs,
610 spiffs_obj_id *obj_id,
611 const u8_t *conflicting_name);
613 s32_t spiffs_obj_lu_find_free(
614 spiffs *fs,
615 spiffs_block_ix starting_block,
616 int starting_lu_entry,
617 spiffs_block_ix *block_ix,
618 int *lu_entry);
620 s32_t spiffs_obj_lu_find_id(
621 spiffs *fs,
622 spiffs_block_ix starting_block,
623 int starting_lu_entry,
624 spiffs_obj_id obj_id,
625 spiffs_block_ix *block_ix,
626 int *lu_entry);
628 s32_t spiffs_obj_lu_find_id_and_span(
629 spiffs *fs,
630 spiffs_obj_id obj_id,
631 spiffs_span_ix spix,
632 spiffs_page_ix exclusion_pix,
633 spiffs_page_ix *pix);
635 s32_t spiffs_obj_lu_find_id_and_span_by_phdr(
636 spiffs *fs,
637 spiffs_obj_id obj_id,
638 spiffs_span_ix spix,
639 spiffs_page_ix exclusion_pix,
640 spiffs_page_ix *pix);
642 // ---------------
644 s32_t spiffs_page_allocate_data(
645 spiffs *fs,
646 spiffs_obj_id obj_id,
647 spiffs_page_header *ph,
648 u8_t *data,
649 u32_t len,
650 u32_t page_offs,
651 u8_t finalize,
652 spiffs_page_ix *pix);
654 s32_t spiffs_page_move(
655 spiffs *fs,
656 spiffs_file fh,
657 u8_t *page_data,
658 spiffs_obj_id obj_id,
659 spiffs_page_header *page_hdr,
660 spiffs_page_ix src_pix,
661 spiffs_page_ix *dst_pix);
663 s32_t spiffs_page_delete(
664 spiffs *fs,
665 spiffs_page_ix pix);
667 // ---------------
669 s32_t spiffs_object_create(
670 spiffs *fs,
671 spiffs_obj_id obj_id,
672 const u8_t name[],
673 const u8_t meta[],
674 spiffs_obj_type type,
675 spiffs_page_ix *objix_hdr_pix);
677 s32_t spiffs_object_update_index_hdr(
678 spiffs *fs,
679 spiffs_fd *fd,
680 spiffs_obj_id obj_id,
681 spiffs_page_ix objix_hdr_pix,
682 u8_t *new_objix_hdr_data,
683 const u8_t name[],
684 const u8_t meta[],
685 u32_t size,
686 spiffs_page_ix *new_pix);
688 #if SPIFFS_IX_MAP
690 s32_t spiffs_populate_ix_map(
691 spiffs *fs,
692 spiffs_fd *fd,
693 u32_t vec_entry_start,
694 u32_t vec_entry_end);
696 #endif
698 void spiffs_cb_object_event(
699 spiffs *fs,
700 spiffs_page_object_ix *objix,
701 int ev,
702 spiffs_obj_id obj_id_raw,
703 spiffs_span_ix spix,
704 spiffs_page_ix new_pix,
705 u32_t new_size);
707 s32_t spiffs_object_open_by_id(
708 spiffs *fs,
709 spiffs_obj_id obj_id,
710 spiffs_fd *fd,
711 spiffs_flags flags,
712 spiffs_mode mode);
714 s32_t spiffs_object_open_by_page(
715 spiffs *fs,
716 spiffs_page_ix pix,
717 spiffs_fd *fd,
718 spiffs_flags flags,
719 spiffs_mode mode);
721 s32_t spiffs_object_append(
722 spiffs_fd *fd,
723 u32_t offset,
724 u8_t *data,
725 u32_t len);
727 s32_t spiffs_object_modify(
728 spiffs_fd *fd,
729 u32_t offset,
730 u8_t *data,
731 u32_t len);
733 s32_t spiffs_object_read(
734 spiffs_fd *fd,
735 u32_t offset,
736 u32_t len,
737 u8_t *dst);
739 s32_t spiffs_object_truncate(
740 spiffs_fd *fd,
741 u32_t new_size,
742 u8_t remove_full);
744 s32_t spiffs_object_find_object_index_header_by_name(
745 spiffs *fs,
746 const u8_t name[SPIFFS_OBJ_NAME_LEN],
747 spiffs_page_ix *pix);
749 // ---------------
751 s32_t spiffs_gc_check(
752 spiffs *fs,
753 u32_t len);
755 s32_t spiffs_gc_erase_page_stats(
756 spiffs *fs,
757 spiffs_block_ix bix);
759 s32_t spiffs_gc_find_candidate(
760 spiffs *fs,
761 spiffs_block_ix **block_candidates,
762 int *candidate_count,
763 char fs_crammed);
765 s32_t spiffs_gc_clean(
766 spiffs *fs,
767 spiffs_block_ix bix);
769 s32_t spiffs_gc_quick(
770 spiffs *fs, u16_t max_free_pages);
772 // ---------------
774 s32_t spiffs_fd_find_new(
775 spiffs *fs,
776 spiffs_fd **fd,
777 const char *name);
779 s32_t spiffs_fd_return(
780 spiffs *fs,
781 spiffs_file f);
783 s32_t spiffs_fd_get(
784 spiffs *fs,
785 spiffs_file f,
786 spiffs_fd **fd);
788 #if SPIFFS_TEMPORAL_FD_CACHE
789 void spiffs_fd_temporal_cache_rehash(
790 spiffs *fs,
791 const char *old_path,
792 const char *new_path);
793 #endif
795 #if SPIFFS_CACHE
796 void spiffs_cache_init(
797 spiffs *fs);
799 void spiffs_cache_drop_page(
800 spiffs *fs,
801 spiffs_page_ix pix);
803 #if SPIFFS_CACHE_WR
804 spiffs_cache_page *spiffs_cache_page_allocate_by_fd(
805 spiffs *fs,
806 spiffs_fd *fd);
808 void spiffs_cache_fd_release(
809 spiffs *fs,
810 spiffs_cache_page *cp);
812 spiffs_cache_page *spiffs_cache_page_get_by_fd(
813 spiffs *fs,
814 spiffs_fd *fd);
815 #endif
816 #endif
818 s32_t spiffs_lookup_consistency_check(
819 spiffs *fs,
820 u8_t check_all_objects);
822 s32_t spiffs_page_consistency_check(
823 spiffs *fs);
825 s32_t spiffs_object_index_consistency_check(
826 spiffs *fs);
828 // memcpy macro,
829 // checked in test builds, otherwise plain memcpy (unless already defined)
830 #ifdef _SPIFFS_TEST
831 #define _SPIFFS_MEMCPY(__d, __s, __l) do { \
832 intptr_t __a1 = (intptr_t)((u8_t*)(__s)); \
833 intptr_t __a2 = (intptr_t)((u8_t*)(__s)+(__l)); \
834 intptr_t __b1 = (intptr_t)((u8_t*)(__d)); \
835 intptr_t __b2 = (intptr_t)((u8_t*)(__d)+(__l)); \
836 if (__a1 <= __b2 && __b1 <= __a2) { \
837 printf("FATAL OVERLAP: memcpy from %lx..%lx to %lx..%lx\n", __a1, __a2, __b1, __b2); \
838 ERREXIT(); \
840 memcpy((__d),(__s),(__l)); \
841 } while (0)
842 #else
843 #ifndef _SPIFFS_MEMCPY
844 #define _SPIFFS_MEMCPY(__d, __s, __l) do{memcpy((__d),(__s),(__l));}while(0)
845 #endif
846 #endif //_SPIFFS_TEST
848 #endif /* SPIFFS_NUCLEUS_H_ */