diff --git a/src/default/spiffs_config.h b/src/default/spiffs_config.h index 65667fc..31c0e27 100644 --- a/src/default/spiffs_config.h +++ b/src/default/spiffs_config.h @@ -119,6 +119,17 @@ #define SPIFFS_USE_MAGIC (0) #endif +#if SPIFFS_USE_MAGIC +// Only valid when SPIFFS_USE_MAGIC is enabled. If SPIFFS_USE_MAGIC_LENGTH is +// enabled, the magic will also be dependent on the length of the filesystem. +// For example, a filesystem configured and formatted for 4 megabytes will not +// be accepted for mounting with a configuration defining the filesystem as 2 +// megabytes. +#ifndef SPIFFS_USE_MAGIC_LENGTH +#define SPIFFS_USE_MAGIC_LENGTH (0) +#endif +#endif + // SPIFFS_LOCK and SPIFFS_UNLOCK protects spiffs from reentrancy on api level // These should be defined on a multithreaded system @@ -131,7 +142,6 @@ #define SPIFFS_UNLOCK(fs) #endif - // Enable if only one spiffs instance with constant configuration will exist // on the target. This will reduce calculations, flash and memory accesses. // Parts of configuration must be defined below instead of at time of mount. diff --git a/src/spiffs.h b/src/spiffs.h index 4b3e768..9a25449 100644 --- a/src/spiffs.h +++ b/src/spiffs.h @@ -282,6 +282,33 @@ typedef struct { // functions +#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH +/** + * Special function. This takes a spiffs config struct and returns + * the number of blocks this file system was formatted with. + * This function relies on following in the passed config struct: + * hal_read_f, phys_addr, and log_page_size. + * + * Do note, that caution should be taken with the value returned here. + * + * There is no check whatsoever that the flash actually contains a file + * system - meaning that just any number could be returned. + * + * There is neither any check that the configuration is set correctly. + * The block size may for instance differ. + * + * One must be sure of the page size and the physical address when + * calling this function. + * + * The resulting value can then be used to set the config structs + * phys_size by multiplying it with the known block size. + * + * @param config essential parts of the physical and logical + * configuration of the file system + */ +s32_t SPIFFS_probe_nbr_of_blocks(spiffs_config *config); +#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH + /** * Initializes the file system dynamic parameters and mounts the filesystem. * If SPIFFS_USE_MAGIC is enabled the mounting may fail with SPIFFS_ERR_NOT_A_FS diff --git a/src/spiffs_hydrogen.c b/src/spiffs_hydrogen.c index 25aae24..d625d7b 100644 --- a/src/spiffs_hydrogen.c +++ b/src/spiffs_hydrogen.c @@ -61,6 +61,17 @@ s32_t SPIFFS_format(spiffs *fs) { return 0; } +#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH + +s32_t SPIFFS_probe_nbr_of_blocks(spiffs_config *config) { + SPIFFS_LOCK(fs); + s32_t block_count = spiffs_probe(config); + SPIFFS_UNLOCK(fs); + return block_count; +} + +#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH + s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work, u8_t *fd_space, u32_t fd_space_size, void *cache, u32_t cache_size, diff --git a/src/spiffs_nucleus.c b/src/spiffs_nucleus.c index ba55722..a9d7005 100644 --- a/src/spiffs_nucleus.c +++ b/src/spiffs_nucleus.c @@ -243,7 +243,7 @@ s32_t spiffs_erase_block( #if SPIFFS_USE_MAGIC // finally, write magic - spiffs_obj_id magic = SPIFFS_MAGIC(fs); + spiffs_obj_id magic = SPIFFS_MAGIC(fs, bix); res = _spiffs_wr(fs, SPIFFS_OP_C_WRTHRU | SPIFFS_OP_T_OBJ_LU2, 0, SPIFFS_MAGIC_PADDR(fs, bix), sizeof(spiffs_obj_id), (u8_t *)&magic); @@ -259,6 +259,30 @@ s32_t spiffs_erase_block( } +#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH +s32_t spiffs_probe( + spiffs_config *cfg) { + s32_t res; + spiffs dummy_fs; // create a dummy fs struct just to be able to use macros + memcpy(&dummy_fs.cfg, cfg, sizeof(spiffs_config)); + spiffs_obj_id magic; + u32_t paddr = SPIFFS_MAGIC_PADDR(&dummy_fs, (spiffs_block_ix)0); +#if SPIFFS_HAL_CALLBACK_EXTRA + // not any proper fs to report here, so callback with null + // (cross fingers that no-one gets angry) + res = cfg->hal_read_f((void *)0, paddr, sizeof(spiffs_obj_id), (u8_t *)&magic); +#else + res = cfg->hal_read_f(paddr, sizeof(spiffs_obj_id), (u8_t *)&magic); +#endif + SPIFFS_CHECK_RES(res); + + // unwind the magic crap to get nbr of blocks + dummy_fs.block_count = 0; + return SPIFFS_MAGIC(&dummy_fs, 0) ^ magic; +} +#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH + + static s32_t spiffs_obj_lu_scan_v( spiffs *fs, spiffs_obj_id obj_id, @@ -311,7 +335,7 @@ s32_t spiffs_obj_lu_scan( sizeof(spiffs_obj_id), (u8_t *)&magic); SPIFFS_CHECK_RES(res); - if (magic != SPIFFS_MAGIC(fs)) { + if (magic != SPIFFS_MAGIC(fs, bix)) { if (unerased_bix == (spiffs_block_ix)-1) { // allow one unerased block as it might be powered down during an erase unerased_bix = bix; diff --git a/src/spiffs_nucleus.h b/src/spiffs_nucleus.h index b64d10c..6e4e8ac 100644 --- a/src/spiffs_nucleus.h +++ b/src/spiffs_nucleus.h @@ -131,7 +131,15 @@ #define SPIFFS_OBJ_ID_DELETED ((spiffs_obj_id)0) #define SPIFFS_OBJ_ID_FREE ((spiffs_obj_id)-1) -#define SPIFFS_MAGIC(fs) ((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs))) +#if SPIFFS_USE_MAGIC +#if !SPIFFS_USE_MAGIC_LENGTH +#define SPIFFS_MAGIC(fs, bix) \ + ((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs))) +#else // SPIFFS_USE_MAGIC_LENGTH +#define SPIFFS_MAGIC(fs, bix) \ + ((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs) ^ ((fs)->block_count - (bix)))) +#endif // SPIFFS_USE_MAGIC_LENGTH +#endif // SPIFFS_USE_MAGIC #define SPIFFS_CONFIG_MAGIC (0x20090315) @@ -530,6 +538,11 @@ s32_t spiffs_erase_block( spiffs *fs, spiffs_block_ix bix); +#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH +s32_t spiffs_probe( + spiffs_config *cfg); +#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH + // --------------- s32_t spiffs_obj_lu_scan( diff --git a/src/test/params_test.h b/src/test/params_test.h index bb5f52d..37fb473 100644 --- a/src/test/params_test.h +++ b/src/test/params_test.h @@ -16,7 +16,9 @@ #define SPIFFS_PHYS_ADDR (4*1024*1024) // test using filesystem magic -//#define SPIFFS_USE_MAGIC 1 +#define SPIFFS_USE_MAGIC 1 +// test using filesystem magic length +#define SPIFFS_USE_MAGIC_LENGTH 1 #define SECTOR_SIZE 65536 #define LOG_BLOCK (SECTOR_SIZE*2) diff --git a/src/test/test_hydrogen.c b/src/test/test_hydrogen.c index 2a83e30..1dfd66f 100644 --- a/src/test/test_hydrogen.c +++ b/src/test/test_hydrogen.c @@ -35,6 +35,76 @@ TEST(info) } TEST_END(info) +#if SPIFFS_USE_MAGIC +TEST(magic) +{ + fs_reset_specific(0, 0, 65536*16, 65536, 65536, 256); + SPIFFS_unmount(FS); + + TEST_CHECK_EQ(fs_mount_specific(0, 65536*16, 65536, 65536, 256), SPIFFS_OK); + SPIFFS_unmount(FS); + + TEST_CHECK_NEQ(fs_mount_specific(0, 65536*16, 65536, 65536, 128), SPIFFS_OK); + TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NOT_A_FS); + + TEST_CHECK_NEQ(fs_mount_specific(4, 65536*16, 65536, 65536, 256), SPIFFS_OK); + TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NOT_A_FS); + + return TEST_RES_OK; +} +TEST_END(magic) + + +#if SPIFFS_USE_MAGIC_LENGTH +TEST(magic_length) +{ + fs_reset_specific(0, 0, 65536*16, 65536, 65536, 256); + SPIFFS_unmount(FS); + + TEST_CHECK_EQ(fs_mount_specific(0, 65536*16, 65536, 65536, 256), SPIFFS_OK); + SPIFFS_unmount(FS); + + TEST_CHECK_NEQ(fs_mount_specific(0, 65536*8, 65536, 65536, 256), SPIFFS_OK); + TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NOT_A_FS); + + TEST_CHECK_NEQ(fs_mount_specific(0, 65536*15, 65536, 65536, 256), SPIFFS_OK); + TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NOT_A_FS); + + TEST_CHECK_NEQ(fs_mount_specific(0, 65536*17, 65536, 65536, 256), SPIFFS_OK); + TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NOT_A_FS); + + TEST_CHECK_NEQ(fs_mount_specific(0, 65536*256, 65536, 65536, 256), SPIFFS_OK); + TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NOT_A_FS); + + return TEST_RES_OK; +} +TEST_END(magic_length) + + +TEST(magic_length_probe) +{ + fs_reset_specific(0, 0, 65536*16, 65536, 65536, 256); + TEST_CHECK_EQ(SPIFFS_probe_nbr_of_blocks(&__fs.cfg), 16); + + fs_reset_specific(0, 0, 65536*24, 65536, 65536, 256); + TEST_CHECK_EQ(SPIFFS_probe_nbr_of_blocks(&__fs.cfg), 24); + + fs_reset_specific(0, 0, 32768*16, 32768, 32768, 128); + TEST_CHECK_EQ(SPIFFS_probe_nbr_of_blocks(&__fs.cfg), 16); + + fs_reset_specific(0, 0, 16384*37, 16384, 16384, 128); + TEST_CHECK_EQ(SPIFFS_probe_nbr_of_blocks(&__fs.cfg), 37); + + fs_reset_specific(0, 0, 4096*11, 4096, 4096, 256); + TEST_CHECK_EQ(SPIFFS_probe_nbr_of_blocks(&__fs.cfg), 11); + + return TEST_RES_OK; +} +TEST_END(magic_length_probe) + +#endif // SPIFFS_USE_MAGIC_LENGTH + +#endif // SPIFFS_USE_MAGIC TEST(missing_file) {