recover_pk.py: replace secp192r1 by prime192v1
[RRG-proxmark3.git] / armsrc / spiffs_nucleus.h
blob5f488ab16d10798305cb29c6bd1c5bb785c292cb
1 //-----------------------------------------------------------------------------
2 // Borrowed initially from https://github.com/pellepl/spiffs
3 // Copyright (c) 2013-2017 Peter Andersson (pelleplutt1976 at gmail.com)
4 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
5 //
6 // This program is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
11 // This program is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
16 // See LICENSE.txt for the text of the license.
17 //-----------------------------------------------------------------------------
19 /* SPIFFS layout
21 * spiffs is designed for following spi flash characteristics:
22 * - only big areas of data (blocks) can be erased
23 * - erasing resets all bits in a block to ones
24 * - writing pulls ones to zeroes
25 * - zeroes cannot be pulled to ones, without erase
26 * - wear leveling
28 * spiffs is also meant to be run on embedded, memory constraint devices.
30 * Entire area is divided in blocks. Entire area is also divided in pages.
31 * Each block contains same number of pages. A page cannot be erased, but a
32 * block can be erased.
34 * Entire area must be block_size * x
35 * page_size must be block_size / (2^y) where y > 2
37 * ex: area = 1024*1024 bytes, block size = 65536 bytes, page size = 256 bytes
39 * BLOCK 0 PAGE 0 object lookup 1
40 * PAGE 1 object lookup 2
41 * ...
42 * PAGE n-1 object lookup n
43 * PAGE n object data 1
44 * PAGE n+1 object data 2
45 * ...
46 * PAGE n+m-1 object data m
48 * BLOCK 1 PAGE n+m object lookup 1
49 * PAGE n+m+1 object lookup 2
50 * ...
51 * PAGE 2n+m-1 object lookup n
52 * PAGE 2n+m object data 1
53 * PAGE 2n+m object data 2
54 * ...
55 * PAGE 2n+2m-1 object data m
56 * ...
58 * n is number of object lookup pages, which is number of pages needed to index all pages
59 * in a block by object id
60 * : block_size / page_size * sizeof(obj_id) / page_size
61 * m is number data pages, which is number of pages in block minus number of lookup pages
62 * : block_size / page_size - block_size / page_size * sizeof(obj_id) / page_size
63 * thus, n+m is total number of pages in a block
64 * : block_size / page_size
66 * ex: n = 65536/256*2/256 = 2, m = 65536/256 - 2 = 254 => n+m = 65536/256 = 256
68 * Object lookup pages contain object id entries. Each entry represent the corresponding
69 * data page.
70 * Assuming a 16 bit object id, an object id being 0xffff represents a free page.
71 * An object id being 0x0000 represents a deleted page.
73 * ex: page 0 : lookup : 0008 0001 0aaa ffff ffff ffff ffff ffff ..
74 * page 1 : lookup : ffff ffff ffff ffff ffff ffff ffff ffff ..
75 * page 2 : data : data for object id 0008
76 * page 3 : data : data for object id 0001
77 * page 4 : data : data for object id 0aaa
78 * ...
81 * Object data pages can be either object index pages or object content.
82 * All object data pages contains a data page header, containing object id and span index.
83 * The span index denotes the object page ordering amongst data pages with same object id.
84 * This applies to both object index pages (when index spans more than one page of entries),
85 * and object data pages.
86 * An object index page contains page entries pointing to object content page. The entry index
87 * in a object index page correlates to the span index in the actual object data page.
88 * The first object index page (span index 0) is called object index header page, and also
89 * contains object flags (directory/file), size, object name etc.
91 * ex:
92 * BLOCK 1
93 * PAGE 256: objectl lookup page 1
94 * [*123] [ 123] [ 123] [ 123]
95 * [ 123] [*123] [ 123] [ 123]
96 * [free] [free] [free] [free] ...
97 * PAGE 257: objectl lookup page 2
98 * [free] [free] [free] [free] ...
99 * PAGE 258: object index page (header)
100 * obj.id:0123 span.ix:0000 flags:INDEX
101 * size:1600 name:ex.txt type:file
102 * [259] [260] [261] [262]
103 * PAGE 259: object data page
104 * obj.id:0123 span.ix:0000 flags:DATA
105 * PAGE 260: object data page
106 * obj.id:0123 span.ix:0001 flags:DATA
107 * PAGE 261: object data page
108 * obj.id:0123 span.ix:0002 flags:DATA
109 * PAGE 262: object data page
110 * obj.id:0123 span.ix:0003 flags:DATA
111 * PAGE 263: object index page
112 * obj.id:0123 span.ix:0001 flags:INDEX
113 * [264] [265] [fre] [fre]
114 * [fre] [fre] [fre] [fre]
115 * PAGE 264: object data page
116 * obj.id:0123 span.ix:0004 flags:DATA
117 * PAGE 265: object data page
118 * obj.id:0123 span.ix:0005 flags:DATA
121 #ifndef SPIFFS_NUCLEUS_H_
122 #define SPIFFS_NUCLEUS_H_
124 #include "common.h"
126 #include "string.h"
127 #include "spiffs.h"
129 #define _SPIFFS_ERR_CHECK_FIRST (SPIFFS_ERR_INTERNAL - 1)
130 #define SPIFFS_ERR_CHECK_OBJ_ID_MISM (SPIFFS_ERR_INTERNAL - 1)
131 #define SPIFFS_ERR_CHECK_SPIX_MISM (SPIFFS_ERR_INTERNAL - 2)
132 #define SPIFFS_ERR_CHECK_FLAGS_BAD (SPIFFS_ERR_INTERNAL - 3)
133 #define _SPIFFS_ERR_CHECK_LAST (SPIFFS_ERR_INTERNAL - 4)
135 // visitor result, continue searching
136 #define SPIFFS_VIS_COUNTINUE (SPIFFS_ERR_INTERNAL - 20)
137 // visitor result, continue searching after reloading lu buffer
138 #define SPIFFS_VIS_COUNTINUE_RELOAD (SPIFFS_ERR_INTERNAL - 21)
139 // visitor result, stop searching
140 #define SPIFFS_VIS_END (SPIFFS_ERR_INTERNAL - 22)
142 // updating an object index contents
143 #define SPIFFS_EV_IX_UPD (0)
144 // creating a new object index
145 #define SPIFFS_EV_IX_NEW (1)
146 // deleting an object index
147 #define SPIFFS_EV_IX_DEL (2)
148 // moving an object index without updating contents
149 #define SPIFFS_EV_IX_MOV (3)
150 // updating an object index header data only, not the table itself
151 #define SPIFFS_EV_IX_UPD_HDR (4)
153 #define SPIFFS_OBJ_ID_IX_FLAG ((spiffs_obj_id)(1<<(8*sizeof(spiffs_obj_id)-1)))
155 #define SPIFFS_UNDEFINED_LEN (u32_t)(-1)
157 #define SPIFFS_OBJ_ID_DELETED ((spiffs_obj_id)0)
158 #define SPIFFS_OBJ_ID_FREE ((spiffs_obj_id)-1)
162 #if defined(__GNUC__) || defined(__clang__) || defined(__TI_COMPILER_VERSION__)
163 /* For GCC, clang and TI compilers */
164 #define SPIFFS_PACKED __attribute__((packed))
165 #elif defined(__ICCARM__) || defined(__CC_ARM)
166 /* For IAR ARM and Keil MDK-ARM compilers */
167 #define SPIFFS_PACKED
169 #else
170 /* Unknown compiler */
171 #define SPIFFS_PACKED
172 #endif
176 #if SPIFFS_USE_MAGIC
177 #if !SPIFFS_USE_MAGIC_LENGTH
178 #define SPIFFS_MAGIC(fs, bix) \
179 ((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs)))
180 #else // SPIFFS_USE_MAGIC_LENGTH
181 #define SPIFFS_MAGIC(fs, bix) \
182 ((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs) ^ ((fs)->block_count - (bix))))
183 #endif // SPIFFS_USE_MAGIC_LENGTH
184 #endif // SPIFFS_USE_MAGIC
186 #define SPIFFS_CONFIG_MAGIC (0x20090315)
188 #if SPIFFS_SINGLETON == 0
189 #define SPIFFS_CFG_LOG_PAGE_SZ(fs) \
190 ((fs)->cfg.log_page_size)
191 #define SPIFFS_CFG_LOG_BLOCK_SZ(fs) \
192 ((fs)->cfg.log_block_size)
193 #define SPIFFS_CFG_PHYS_SZ(fs) \
194 ((fs)->cfg.phys_size)
195 #define SPIFFS_CFG_PHYS_ERASE_SZ(fs) \
196 ((fs)->cfg.phys_erase_block)
197 #define SPIFFS_CFG_PHYS_ADDR(fs) \
198 ((fs)->cfg.phys_addr)
199 #endif
201 // total number of pages
202 #define SPIFFS_MAX_PAGES(fs) \
203 ( SPIFFS_CFG_PHYS_SZ(fs)/SPIFFS_CFG_LOG_PAGE_SZ(fs) )
204 // total number of pages per block, including object lookup pages
205 #define SPIFFS_PAGES_PER_BLOCK(fs) \
206 ( SPIFFS_CFG_LOG_BLOCK_SZ(fs)/SPIFFS_CFG_LOG_PAGE_SZ(fs) )
207 // number of object lookup pages per block
208 #define SPIFFS_OBJ_LOOKUP_PAGES(fs) \
209 (MAX(1, (SPIFFS_PAGES_PER_BLOCK(fs) * sizeof(spiffs_obj_id)) / SPIFFS_CFG_LOG_PAGE_SZ(fs)) )
210 // checks if page index belongs to object lookup
211 #define SPIFFS_IS_LOOKUP_PAGE(fs,pix) \
212 (((pix) % SPIFFS_PAGES_PER_BLOCK(fs)) < SPIFFS_OBJ_LOOKUP_PAGES(fs))
213 // number of object lookup entries in all object lookup pages
214 #define SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs) \
215 (SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs))
216 // converts a block to physical address
217 #define SPIFFS_BLOCK_TO_PADDR(fs, block) \
218 ( SPIFFS_CFG_PHYS_ADDR(fs) + (block)* SPIFFS_CFG_LOG_BLOCK_SZ(fs) )
219 // converts a object lookup entry to page index
220 #define SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, block, entry) \
221 ((block)*SPIFFS_PAGES_PER_BLOCK(fs) + (SPIFFS_OBJ_LOOKUP_PAGES(fs) + entry))
222 // converts a object lookup entry to physical address of corresponding page
223 #define SPIFFS_OBJ_LOOKUP_ENTRY_TO_PADDR(fs, block, entry) \
224 (SPIFFS_BLOCK_TO_PADDR(fs, block) + (SPIFFS_OBJ_LOOKUP_PAGES(fs) + entry) * SPIFFS_CFG_LOG_PAGE_SZ(fs) )
225 // converts a page to physical address
226 #define SPIFFS_PAGE_TO_PADDR(fs, page) \
227 ( SPIFFS_CFG_PHYS_ADDR(fs) + (page) * SPIFFS_CFG_LOG_PAGE_SZ(fs) )
228 // converts a physical address to page
229 #define SPIFFS_PADDR_TO_PAGE(fs, addr) \
230 ( ((addr) - SPIFFS_CFG_PHYS_ADDR(fs)) / SPIFFS_CFG_LOG_PAGE_SZ(fs) )
231 // gives index in page for a physical address
232 #define SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr) \
233 ( ((addr) - SPIFFS_CFG_PHYS_ADDR(fs)) % SPIFFS_CFG_LOG_PAGE_SZ(fs) )
234 // returns containing block for given page
235 #define SPIFFS_BLOCK_FOR_PAGE(fs, page) \
236 ( (page) / SPIFFS_PAGES_PER_BLOCK(fs) )
237 // returns starting page for block
238 #define SPIFFS_PAGE_FOR_BLOCK(fs, block) \
239 ( (block) * SPIFFS_PAGES_PER_BLOCK(fs) )
240 // converts page to entry in object lookup page
241 #define SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, page) \
242 ( (page) % SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs) )
243 // returns data size in a data page
244 #define SPIFFS_DATA_PAGE_SIZE(fs) \
245 ( SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_header) )
246 // returns physical address for block's erase count,
247 // always in the physical last entry of the last object lookup page
248 #define SPIFFS_ERASE_COUNT_PADDR(fs, bix) \
249 ( SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_OBJ_LOOKUP_PAGES(fs) * SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_obj_id) )
250 // returns physical address for block's magic,
251 // always in the physical second last entry of the last object lookup page
252 #define SPIFFS_MAGIC_PADDR(fs, bix) \
253 ( SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_OBJ_LOOKUP_PAGES(fs) * SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_obj_id)*2 )
254 // checks if there is any room for magic in the object luts
255 #define SPIFFS_CHECK_MAGIC_POSSIBLE(fs) \
256 ( (SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs) % (SPIFFS_CFG_LOG_PAGE_SZ(fs)/sizeof(spiffs_obj_id))) * sizeof(spiffs_obj_id) \
257 <= (SPIFFS_CFG_LOG_PAGE_SZ(fs)-sizeof(spiffs_obj_id)*2) )
259 // define helpers object
261 // entries in an object header page index
262 #define SPIFFS_OBJ_HDR_IX_LEN(fs) \
263 ((SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_object_ix_header))/sizeof(spiffs_page_ix))
264 // entries in an object page index
265 #define SPIFFS_OBJ_IX_LEN(fs) \
266 ((SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_object_ix))/sizeof(spiffs_page_ix))
267 // object index entry for given data span index
268 #define SPIFFS_OBJ_IX_ENTRY(fs, spix) \
269 ((spix) < SPIFFS_OBJ_HDR_IX_LEN(fs) ? (spix) : (((spix)-SPIFFS_OBJ_HDR_IX_LEN(fs))%SPIFFS_OBJ_IX_LEN(fs)))
270 // object index span index number for given data span index or entry
271 #define SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, spix) \
272 ((spix) < SPIFFS_OBJ_HDR_IX_LEN(fs) ? 0 : (1+((spix)-SPIFFS_OBJ_HDR_IX_LEN(fs))/SPIFFS_OBJ_IX_LEN(fs)))
273 // get data span index for object index span index
274 #define SPIFFS_DATA_SPAN_IX_FOR_OBJ_IX_SPAN_IX(fs, spix) \
275 ( (spix) == 0 ? 0 : (SPIFFS_OBJ_HDR_IX_LEN(fs) + (((spix)-1) * SPIFFS_OBJ_IX_LEN(fs))) )
277 #if SPIFFS_FILEHDL_OFFSET
278 #define SPIFFS_FH_OFFS(fs, fh) ((fh) != 0 ? ((fh) + (fs)->cfg.fh_ix_offset) : 0)
279 #define SPIFFS_FH_UNOFFS(fs, fh) ((fh) != 0 ? ((fh) - (fs)->cfg.fh_ix_offset) : 0)
280 #else
281 #define SPIFFS_FH_OFFS(fs, fh) (fh)
282 #define SPIFFS_FH_UNOFFS(fs, fh) (fh)
283 #endif
286 #define SPIFFS_OP_T_OBJ_LU (0<<0)
287 #define SPIFFS_OP_T_OBJ_LU2 (1<<0)
288 #define SPIFFS_OP_T_OBJ_IX (2<<0)
289 #define SPIFFS_OP_T_OBJ_DA (3<<0)
290 #define SPIFFS_OP_C_DELE (0<<2)
291 #define SPIFFS_OP_C_UPDT (1<<2)
292 #define SPIFFS_OP_C_MOVS (2<<2)
293 #define SPIFFS_OP_C_MOVD (3<<2)
294 #define SPIFFS_OP_C_FLSH (4<<2)
295 #define SPIFFS_OP_C_READ (5<<2)
296 #define SPIFFS_OP_C_WRTHRU (6<<2)
298 #define SPIFFS_OP_TYPE_MASK (3<<0)
299 #define SPIFFS_OP_COM_MASK (7<<2)
302 // if 0, this page is written to, else clean
303 #define SPIFFS_PH_FLAG_USED (1<<0)
304 // if 0, writing is finalized, else under modification
305 #define SPIFFS_PH_FLAG_FINAL (1<<1)
306 // if 0, this is an index page, else a data page
307 #define SPIFFS_PH_FLAG_INDEX (1<<2)
308 // if 0, page is deleted, else valid
309 #define SPIFFS_PH_FLAG_DELET (1<<7)
310 // if 0, this index header is being deleted
311 #define SPIFFS_PH_FLAG_IXDELE (1<<6)
314 #define SPIFFS_CHECK_MOUNT(fs) \
315 ((fs)->mounted != 0)
317 #define SPIFFS_CHECK_CFG(fs) \
318 ((fs)->config_magic == SPIFFS_CONFIG_MAGIC)
320 #define SPIFFS_CHECK_RES(res) \
321 do { \
322 if ((res) < SPIFFS_OK) return (res); \
323 } while (0);
325 #define SPIFFS_API_CHECK_MOUNT(fs) \
326 if (!SPIFFS_CHECK_MOUNT((fs))) { \
327 (fs)->err_code = SPIFFS_ERR_NOT_MOUNTED; \
328 return SPIFFS_ERR_NOT_MOUNTED; \
331 #define SPIFFS_API_CHECK_CFG(fs) \
332 if (!SPIFFS_CHECK_CFG((fs))) { \
333 (fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED; \
334 return SPIFFS_ERR_NOT_CONFIGURED; \
337 #define SPIFFS_API_CHECK_RES(fs, res) \
338 if ((res) < SPIFFS_OK) { \
339 (fs)->err_code = (res); \
340 return (res); \
343 #define SPIFFS_API_CHECK_RES_UNLOCK(fs, res) \
344 if ((res) < SPIFFS_OK) { \
345 (fs)->err_code = (res); \
346 SPIFFS_UNLOCK(fs); \
347 return (res); \
350 #define SPIFFS_VALIDATE_OBJIX(ph, objid, spix) \
351 if (((ph).flags & SPIFFS_PH_FLAG_USED) != 0) return SPIFFS_ERR_IS_FREE; \
352 if (((ph).flags & SPIFFS_PH_FLAG_DELET) == 0) return SPIFFS_ERR_DELETED; \
353 if (((ph).flags & SPIFFS_PH_FLAG_FINAL) != 0) return SPIFFS_ERR_NOT_FINALIZED; \
354 if (((ph).flags & SPIFFS_PH_FLAG_INDEX) != 0) return SPIFFS_ERR_NOT_INDEX; \
355 if (((objid) & SPIFFS_OBJ_ID_IX_FLAG) == 0) return SPIFFS_ERR_NOT_INDEX; \
356 if ((ph).span_ix != (spix)) return SPIFFS_ERR_INDEX_SPAN_MISMATCH;
357 //if ((spix) == 0 && ((ph).flags & SPIFFS_PH_FLAG_IXDELE) == 0) return SPIFFS_ERR_DELETED;
359 #define SPIFFS_VALIDATE_DATA(ph, objid, spix) \
360 if (((ph).flags & SPIFFS_PH_FLAG_USED) != 0) return SPIFFS_ERR_IS_FREE; \
361 if (((ph).flags & SPIFFS_PH_FLAG_DELET) == 0) return SPIFFS_ERR_DELETED; \
362 if (((ph).flags & SPIFFS_PH_FLAG_FINAL) != 0) return SPIFFS_ERR_NOT_FINALIZED; \
363 if (((ph).flags & SPIFFS_PH_FLAG_INDEX) == 0) return SPIFFS_ERR_IS_INDEX; \
364 if ((objid) & SPIFFS_OBJ_ID_IX_FLAG) return SPIFFS_ERR_IS_INDEX; \
365 if ((ph).span_ix != (spix)) return SPIFFS_ERR_DATA_SPAN_MISMATCH;
368 // check id, only visit matching objec ids
369 #define SPIFFS_VIS_CHECK_ID (1<<0)
370 // report argument object id to visitor - else object lookup id is reported
371 #define SPIFFS_VIS_CHECK_PH (1<<1)
372 // stop searching at end of all look up pages
373 #define SPIFFS_VIS_NO_WRAP (1<<2)
375 #if SPIFFS_HAL_CALLBACK_EXTRA
377 #define SPIFFS_HAL_WRITE(_fs, _paddr, _len, _src) \
378 (_fs)->cfg.hal_write_f((_fs), (_paddr), (_len), (_src))
379 #define SPIFFS_HAL_READ(_fs, _paddr, _len, _dst) \
380 (_fs)->cfg.hal_read_f((_fs), (_paddr), (_len), (_dst))
381 #define SPIFFS_HAL_ERASE(_fs, _paddr, _len) \
382 (_fs)->cfg.hal_erase_f((_fs), (_paddr), (_len))
384 #else // SPIFFS_HAL_CALLBACK_EXTRA
386 #define SPIFFS_HAL_WRITE(_fs, _paddr, _len, _src) \
387 (_fs)->cfg.hal_write_f((_paddr), (_len), (_src))
388 #define SPIFFS_HAL_READ(_fs, _paddr, _len, _dst) \
389 (_fs)->cfg.hal_read_f((_paddr), (_len), (_dst))
390 #define SPIFFS_HAL_ERASE(_fs, _paddr, _len) \
391 (_fs)->cfg.hal_erase_f((_paddr), (_len))
393 #endif // SPIFFS_HAL_CALLBACK_EXTRA
395 #if SPIFFS_CACHE
397 #define SPIFFS_CACHE_FLAG_DIRTY (1<<0)
398 #define SPIFFS_CACHE_FLAG_WRTHRU (1<<1)
399 #define SPIFFS_CACHE_FLAG_OBJLU (1<<2)
400 #define SPIFFS_CACHE_FLAG_OBJIX (1<<3)
401 #define SPIFFS_CACHE_FLAG_DATA (1<<4)
402 #define SPIFFS_CACHE_FLAG_TYPE_WR (1<<7)
404 #define SPIFFS_CACHE_PAGE_SIZE(fs) \
405 (sizeof(spiffs_cache_page) + SPIFFS_CFG_LOG_PAGE_SZ(fs))
407 #define spiffs_get_cache(fs) \
408 ((spiffs_cache *)((fs)->cache))
410 #define spiffs_get_cache_page_hdr(fs, c, ix) \
411 ((spiffs_cache_page *)(&((c)->cpages[(ix) * SPIFFS_CACHE_PAGE_SIZE(fs)])))
413 #define spiffs_get_cache_page(fs, c, ix) \
414 ((u8_t *)(&((c)->cpages[(ix) * SPIFFS_CACHE_PAGE_SIZE(fs)])) + sizeof(spiffs_cache_page))
416 // cache page struct
417 typedef struct {
418 // cache flags
419 u8_t flags;
420 // cache page index
421 u8_t ix;
422 // last access of this cache page
423 u32_t last_access;
424 union {
425 // type read cache
426 struct spix {
427 // read cache page index
428 spiffs_page_ix pix;
429 } spix;
430 #if SPIFFS_CACHE_WR
431 // type write cache
432 struct swrc {
433 // write cache
434 spiffs_obj_id obj_id;
435 // offset in cache page
436 u32_t offset;
437 // size of cache page
438 u16_t size;
439 } swrc;
440 #endif
441 } ucache;
442 } spiffs_cache_page;
444 // cache struct
445 typedef struct {
446 u8_t cpage_count;
447 u32_t last_access;
448 u32_t cpage_use_map;
449 u32_t cpage_use_mask;
450 u8_t *cpages;
451 } spiffs_cache;
453 #endif
456 // spiffs nucleus file descriptor
457 typedef struct {
458 // the filesystem of this descriptor
459 spiffs *fs;
460 // number of file descriptor - if 0, the file descriptor is closed
461 spiffs_file file_nbr;
462 // object id - if SPIFFS_OBJ_ID_ERASED, the file was deleted
463 spiffs_obj_id obj_id;
464 // size of the file
465 u32_t size;
466 // cached object index header page index
467 spiffs_page_ix objix_hdr_pix;
468 // cached offset object index page index
469 spiffs_page_ix cursor_objix_pix;
470 // cached offset object index span index
471 spiffs_span_ix cursor_objix_spix;
472 // current absolute offset
473 u32_t offset;
474 // current file descriptor offset (cached)
475 u32_t fdoffset;
476 // fd flags
477 spiffs_flags flags;
478 #if SPIFFS_CACHE_WR
479 spiffs_cache_page *cache_page;
480 #endif
481 #if SPIFFS_TEMPORAL_FD_CACHE
482 // djb2 hash of filename
483 u32_t name_hash;
484 // hit score (score == 0 indicates never used fd)
485 u16_t score;
486 #endif
487 #if SPIFFS_IX_MAP
488 // spiffs index map, if 0 it means unmapped
489 spiffs_ix_map *ix_map;
490 #endif
491 } spiffs_fd;
494 // object structs
496 // page header, part of each page except object lookup pages
497 // NB: this is always aligned when the data page is an object index,
498 // as in this case struct spiffs_page_object_ix is used
499 typedef struct SPIFFS_PACKED {
500 // object id
501 spiffs_obj_id obj_id;
502 // object span index
503 spiffs_span_ix span_ix;
504 // flags
505 u8_t flags;
506 } spiffs_page_header;
508 // object index header page header
509 typedef struct SPIFFS_PACKED
510 #if SPIFFS_ALIGNED_OBJECT_INDEX_TABLES
511 __attribute((aligned(sizeof(spiffs_page_ix))))
512 #endif
514 // common page header
515 spiffs_page_header p_hdr;
516 // alignment
517 u8_t _align[4 - ((sizeof(spiffs_page_header) & 3) == 0 ? 4 : (sizeof(spiffs_page_header) & 3))];
518 // size of object
519 u32_t size;
520 // type of object
521 spiffs_obj_type type;
522 // name of object
523 u8_t name[SPIFFS_OBJ_NAME_LEN];
524 #if SPIFFS_OBJ_META_LEN
525 // metadata. not interpreted by SPIFFS in any way.
526 u8_t meta[SPIFFS_OBJ_META_LEN];
527 #endif
529 spiffs_page_object_ix_header;
531 // object index page header
532 typedef struct SPIFFS_PACKED {
533 spiffs_page_header p_hdr;
534 u8_t _align[4 - ((sizeof(spiffs_page_header) & 3) == 0 ? 4 : (sizeof(spiffs_page_header) & 3))];
535 } spiffs_page_object_ix;
537 // callback func for object lookup visitor
538 typedef s32_t (*spiffs_visitor_f)(spiffs *fs, spiffs_obj_id id, spiffs_block_ix bix, int ix_entry,
539 const void *user_const_p, void *user_var_p);
542 #if SPIFFS_CACHE
543 #define _spiffs_rd(fs, op, fh, addr, len, dst) \
544 spiffs_phys_rd((fs), (op), (fh), (addr), (len), (dst))
545 #define _spiffs_wr(fs, op, fh, addr, len, src) \
546 spiffs_phys_wr((fs), (op), (fh), (addr), (len), (src))
547 #else
548 #define _spiffs_rd(fs, op, fh, addr, len, dst) \
549 spiffs_phys_rd((fs), (addr), (len), (dst))
550 #define _spiffs_wr(fs, op, fh, addr, len, src) \
551 spiffs_phys_wr((fs), (addr), (len), (src))
552 #endif
554 #ifndef MIN
555 #define MIN(a,b) ((a) < (b) ? (a) : (b))
556 #endif
557 #ifndef MAX
558 #define MAX(a,b) ((a) > (b) ? (a) : (b))
559 #endif
561 // ---------------
563 s32_t spiffs_phys_rd(
564 spiffs *fs,
565 #if SPIFFS_CACHE
566 u8_t op,
567 spiffs_file fh,
568 #endif
569 u32_t addr,
570 u32_t len,
571 u8_t *dst);
573 s32_t spiffs_phys_wr(
574 spiffs *fs,
575 #if SPIFFS_CACHE
576 u8_t op,
577 spiffs_file fh,
578 #endif
579 u32_t addr,
580 u32_t len,
581 u8_t *src);
583 s32_t spiffs_phys_cpy(
584 spiffs *fs,
585 spiffs_file fh,
586 u32_t dst,
587 u32_t src,
588 u32_t len);
590 s32_t spiffs_phys_count_free_blocks(
591 spiffs *fs);
593 s32_t spiffs_obj_lu_find_entry_visitor(
594 spiffs *fs,
595 spiffs_block_ix starting_block,
596 int starting_lu_entry,
597 u8_t flags,
598 spiffs_obj_id obj_id,
599 spiffs_visitor_f v,
600 const void *user_const_p,
601 void *user_var_p,
602 spiffs_block_ix *block_ix,
603 int *lu_entry);
605 s32_t spiffs_erase_block(
606 spiffs *fs,
607 spiffs_block_ix bix);
609 #if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
610 s32_t spiffs_probe(
611 spiffs_config *cfg);
612 #endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
614 // ---------------
616 s32_t spiffs_obj_lu_scan(
617 spiffs *fs);
619 s32_t spiffs_obj_lu_find_free_obj_id(
620 spiffs *fs,
621 spiffs_obj_id *obj_id,
622 const u8_t *conflicting_name);
624 s32_t spiffs_obj_lu_find_free(
625 spiffs *fs,
626 spiffs_block_ix starting_block,
627 int starting_lu_entry,
628 spiffs_block_ix *block_ix,
629 int *lu_entry);
631 s32_t spiffs_obj_lu_find_id(
632 spiffs *fs,
633 spiffs_block_ix starting_block,
634 int starting_lu_entry,
635 spiffs_obj_id obj_id,
636 spiffs_block_ix *block_ix,
637 int *lu_entry);
639 s32_t spiffs_obj_lu_find_id_and_span(
640 spiffs *fs,
641 spiffs_obj_id obj_id,
642 spiffs_span_ix spix,
643 spiffs_page_ix exclusion_pix,
644 spiffs_page_ix *pix);
646 s32_t spiffs_obj_lu_find_id_and_span_by_phdr(
647 spiffs *fs,
648 spiffs_obj_id obj_id,
649 spiffs_span_ix spix,
650 spiffs_page_ix exclusion_pix,
651 spiffs_page_ix *pix);
653 // ---------------
655 s32_t spiffs_page_allocate_data(
656 spiffs *fs,
657 spiffs_obj_id obj_id,
658 spiffs_page_header *ph,
659 u8_t *data,
660 u32_t len,
661 u32_t page_offs,
662 u8_t finalize,
663 spiffs_page_ix *pix);
665 s32_t spiffs_page_move(
666 spiffs *fs,
667 spiffs_file fh,
668 u8_t *page_data,
669 spiffs_obj_id obj_id,
670 spiffs_page_header *page_hdr,
671 spiffs_page_ix src_pix,
672 spiffs_page_ix *dst_pix);
674 s32_t spiffs_page_delete(
675 spiffs *fs,
676 spiffs_page_ix pix);
678 // ---------------
680 s32_t spiffs_object_create(
681 spiffs *fs,
682 spiffs_obj_id obj_id,
683 const u8_t name[],
684 const u8_t meta[],
685 spiffs_obj_type type,
686 spiffs_page_ix *objix_hdr_pix);
688 s32_t spiffs_object_update_index_hdr(
689 spiffs *fs,
690 spiffs_fd *fd,
691 spiffs_obj_id obj_id,
692 spiffs_page_ix objix_hdr_pix,
693 u8_t *new_objix_hdr_data,
694 const u8_t name[],
695 const u8_t meta[],
696 u32_t size,
697 spiffs_page_ix *new_pix);
699 #if SPIFFS_IX_MAP
701 s32_t spiffs_populate_ix_map(
702 spiffs *fs,
703 spiffs_fd *fd,
704 u32_t vec_entry_start,
705 u32_t vec_entry_end);
707 #endif
709 void spiffs_cb_object_event(
710 spiffs *fs,
711 spiffs_page_object_ix *objix,
712 int ev,
713 spiffs_obj_id obj_id_raw,
714 spiffs_span_ix spix,
715 spiffs_page_ix new_pix,
716 u32_t new_size);
718 s32_t spiffs_object_open_by_id(
719 spiffs *fs,
720 spiffs_obj_id obj_id,
721 spiffs_fd *fd,
722 spiffs_flags flags,
723 spiffs_mode mode);
725 s32_t spiffs_object_open_by_page(
726 spiffs *fs,
727 spiffs_page_ix pix,
728 spiffs_fd *fd,
729 spiffs_flags flags,
730 spiffs_mode mode);
732 s32_t spiffs_object_append(
733 spiffs_fd *fd,
734 u32_t offset,
735 u8_t *data,
736 u32_t len);
738 s32_t spiffs_object_modify(
739 spiffs_fd *fd,
740 u32_t offset,
741 u8_t *data,
742 u32_t len);
744 s32_t spiffs_object_read(
745 spiffs_fd *fd,
746 u32_t offset,
747 u32_t len,
748 u8_t *dst);
750 s32_t spiffs_object_truncate(
751 spiffs_fd *fd,
752 u32_t new_size,
753 u8_t remove_full);
755 s32_t spiffs_object_find_object_index_header_by_name(
756 spiffs *fs,
757 const u8_t name[SPIFFS_OBJ_NAME_LEN],
758 spiffs_page_ix *pix);
760 // ---------------
762 s32_t spiffs_gc_check(
763 spiffs *fs,
764 u32_t len);
766 s32_t spiffs_gc_erase_page_stats(
767 spiffs *fs,
768 spiffs_block_ix bix);
770 s32_t spiffs_gc_find_candidate(
771 spiffs *fs,
772 spiffs_block_ix **block_candidates,
773 int *candidate_count,
774 char fs_crammed);
776 s32_t spiffs_gc_clean(
777 spiffs *fs,
778 spiffs_block_ix bix);
780 s32_t spiffs_gc_quick(
781 spiffs *fs, u16_t max_free_pages);
783 // ---------------
785 s32_t spiffs_fd_find_new(
786 spiffs *fs,
787 spiffs_fd **fd,
788 const char *name);
790 s32_t spiffs_fd_return(
791 spiffs *fs,
792 spiffs_file f);
794 s32_t spiffs_fd_get(
795 spiffs *fs,
796 spiffs_file f,
797 spiffs_fd **fd);
799 #if SPIFFS_TEMPORAL_FD_CACHE
800 void spiffs_fd_temporal_cache_rehash(
801 spiffs *fs,
802 const char *old_path,
803 const char *new_path);
804 #endif
806 #if SPIFFS_CACHE
807 void spiffs_cache_init(
808 spiffs *fs);
810 void spiffs_cache_drop_page(
811 spiffs *fs,
812 spiffs_page_ix pix);
814 #if SPIFFS_CACHE_WR
815 spiffs_cache_page *spiffs_cache_page_allocate_by_fd(
816 spiffs *fs,
817 spiffs_fd *fd);
819 void spiffs_cache_fd_release(
820 spiffs *fs,
821 spiffs_cache_page *cp);
823 spiffs_cache_page *spiffs_cache_page_get_by_fd(
824 spiffs *fs,
825 spiffs_fd *fd);
826 #endif
827 #endif
829 s32_t spiffs_lookup_consistency_check(
830 spiffs *fs,
831 u8_t check_all_objects);
833 s32_t spiffs_page_consistency_check(
834 spiffs *fs);
836 s32_t spiffs_object_index_consistency_check(
837 spiffs *fs);
839 // memcpy macro,
840 // checked in test builds, otherwise plain memcpy (unless already defined)
841 #ifdef _SPIFFS_TEST
842 #define _SPIFFS_MEMCPY(__d, __s, __l) do { \
843 intptr_t __a1 = (intptr_t)((u8_t*)(__s)); \
844 intptr_t __a2 = (intptr_t)((u8_t*)(__s)+(__l)); \
845 intptr_t __b1 = (intptr_t)((u8_t*)(__d)); \
846 intptr_t __b2 = (intptr_t)((u8_t*)(__d)+(__l)); \
847 if (__a1 <= __b2 && __b1 <= __a2) { \
848 printf("FATAL OVERLAP: memcpy from %lx..%lx to %lx..%lx\n", __a1, __a2, __b1, __b2); \
849 ERREXIT(); \
851 memcpy((__d),(__s),(__l)); \
852 } while (0)
853 #else
854 #ifndef _SPIFFS_MEMCPY
855 #define _SPIFFS_MEMCPY(__d, __s, __l) do{memcpy((__d),(__s),(__l));}while(0)
856 #endif
857 #endif //_SPIFFS_TEST
859 #endif /* SPIFFS_NUCLEUS_H_ */