From afa37eef2cc6d1255d42dea213f4d44b9a8fbe6a Mon Sep 17 00:00:00 2001 From: Lucjan Bryndza Date: Thu, 17 Dec 2020 15:52:39 +0100 Subject: [PATCH] [EGD-4758] Add block size and fs size Add blocks size and blocks count detecting of the file size. --- .../src/purefs/fs/filesystem_littlefs.cpp | 46 ++++++++++--- module-vfs/thirdparty/lfsfs/CMakeLists.txt | 7 +- .../lfsextension/include/lfs_extension.h | 21 ++++++ .../lfsfs/lfsextension/src/lfs_extension.c | 68 +++++++++++++++++++ 4 files changed, 131 insertions(+), 11 deletions(-) create mode 100644 module-vfs/thirdparty/lfsfs/lfsextension/include/lfs_extension.h create mode 100644 module-vfs/thirdparty/lfsfs/lfsextension/src/lfs_extension.c diff --git a/module-vfs/drivers/src/purefs/fs/filesystem_littlefs.cpp b/module-vfs/drivers/src/purefs/fs/filesystem_littlefs.cpp index 7b4af5a2e5a909062a00f9d5f37ed68dc3aa5e8d..a91b2772bd42bcdf6bc37aa61c478f6e3f2ee05a 100644 --- a/module-vfs/drivers/src/purefs/fs/filesystem_littlefs.cpp +++ b/module-vfs/drivers/src/purefs/fs/filesystem_littlefs.cpp @@ -6,10 +6,13 @@ #include #include #include +#include +#include #include +#include #include -#include +#include #include #include #include @@ -103,19 +106,33 @@ namespace st.st_mode = translate_attrib_to_st_mode(fs.type); } - [[gnu::nonnull(1)]] void setup_lfs_config(lfs_config *cfg) + [[gnu::nonnull(1)]] int setup_lfs_config(lfs_config *cfg, size_t sector_size, size_t part_sectors_count) { cfg->block_cycles = 512; cfg->block_size = 0; // Read later from superblock cfg->block_count = 0; // Read later from super block cfg->lookahead_size = 8192; - // TODO: Read lfs configuration from the superblock - cfg->block_size = 4096; - cfg->read_size = cfg->block_size; - cfg->prog_size = cfg->block_size; - cfg->cache_size = cfg->block_size; - cfg->block_count = 261887; + + int err = lfs_extension_read_config_from_superblock(cfg, sector_size); + if (err) { + LOG_ERROR("Unable to read the superblock info %i", err); + return lfs_to_errno(err); + } + if (cfg->block_size > 1024U * 1024U) { + LOG_ERROR("Block size too big"); + return -E2BIG; + } + + if ((uint64_t(cfg->block_count) * uint64_t(cfg->block_size)) / sector_size > part_sectors_count) { + LOG_ERROR("Block count out of range sectors count"); + return -ERANGE; + } + cfg->read_size = cfg->block_size; + cfg->prog_size = cfg->block_size; + cfg->cache_size = cfg->block_size; + return 0; } + } // namespace namespace purefs::fs::drivers @@ -226,10 +243,21 @@ namespace purefs::fs::drivers } cpp_freertos::LockGuard _lck(m_lock); auto err = littlefs::internal::append_volume(vmnt->lfs_config(), disk_mngr(), disk); + if (err) { + return lfs_to_errno(err); + } + { + auto diskmm = disk_mngr(); + auto ssize = diskmm->get_info(disk, blkdev::info_type::sector_size); + if (ssize < 0) { + LOG_ERROR("Unable to read sector size %i", int(ssize)); + return ssize; + } + err = setup_lfs_config(vmnt->lfs_config(), ssize, disk->sectors()); + } if (err) { return err; } - setup_lfs_config(vmnt->lfs_config()); err = lfs_mount(vmnt->lfs_mount(), vmnt->lfs_config()); if (err) { LOG_ERROR("LFS mount error %i", err); diff --git a/module-vfs/thirdparty/lfsfs/CMakeLists.txt b/module-vfs/thirdparty/lfsfs/CMakeLists.txt index 62b302334e848ca3fb361b147ccd969949ed2a2c..6aa1d96e916da7b771aa1197c1cebd25633622b8 100644 --- a/module-vfs/thirdparty/lfsfs/CMakeLists.txt +++ b/module-vfs/thirdparty/lfsfs/CMakeLists.txt @@ -5,6 +5,8 @@ project(littlefs LANGUAGES C) include(thirdparty OPTIONAL) set(LIBLITTLEFS_SRCDIR littlefs) +set(LIBLITTLEFS_SRCDIR_EXT lfsextension/src) +set(LIBLITTLEFS_INCDIR_EXT lfsextension/include) set(LIBLITTLEFS_TARGET ${PROJECT_NAME}) set(LIBLITTLEFS_SOURCES @@ -13,10 +15,11 @@ set(LIBLITTLEFS_SOURCES ${LIBLITTLEFS_SRCDIR}/bd/lfs_filebd.c ${LIBLITTLEFS_SRCDIR}/bd/lfs_rambd.c ${LIBLITTLEFS_SRCDIR}/bd/lfs_testbd.c + ${LIBLITTLEFS_SRCDIR_EXT}/lfs_extension.c ) -set( LIBLITTLEFS_PUBLIC_INCLUDES ${LIBLITTLEFS_SRCDIR}) -set( LIBLITTLEFS_PRIVATE_INCLUDES ${LIBLITTLEFS_SRCDIR}/bd) +set( LIBLITTLEFS_PUBLIC_INCLUDES ${LIBLITTLEFS_SRCDIR} ${LIBLITTLEFS_INCDIR_EXT}) +set( LIBLITTLEFS_PRIVATE_INCLUDES ${LIBLITTLEFS_SRCDIR}/bd ) add_library( ${LIBLITTLEFS_TARGET} STATIC ${LIBLITTLEFS_SOURCES} ) diff --git a/module-vfs/thirdparty/lfsfs/lfsextension/include/lfs_extension.h b/module-vfs/thirdparty/lfsfs/lfsextension/include/lfs_extension.h new file mode 100644 index 0000000000000000000000000000000000000000..a6ed570ea48534d6f7530c4d8d111996f4cd038a --- /dev/null +++ b/module-vfs/thirdparty/lfsfs/lfsextension/include/lfs_extension.h @@ -0,0 +1,21 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#pragma once + +#include "lfs.h" + +#ifdef __cplusplus +extern "C" +{ +#endif + /** + * Try to setup config structure based on the superblock information + * @param cfg LFS config structure + * @return 0 or success otherwise error + */ + int lfs_extension_read_config_from_superblock(struct lfs_config *cfg, size_t sector_size) + __attribute__((nonnull(1))); +#ifdef __cplusplus +} +#endif diff --git a/module-vfs/thirdparty/lfsfs/lfsextension/src/lfs_extension.c b/module-vfs/thirdparty/lfsfs/lfsextension/src/lfs_extension.c new file mode 100644 index 0000000000000000000000000000000000000000..65d3bcd2b9fdc4b549bfaf885e352afb075664a0 --- /dev/null +++ b/module-vfs/thirdparty/lfsfs/lfsextension/src/lfs_extension.c @@ -0,0 +1,68 @@ +// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved. +// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md + +#include "lfs_extension.h" +#include "lfs_util.h" + +static inline void lfs_superblock_fromle32(lfs_superblock_t *superblock) +{ + superblock->version = lfs_fromle32(superblock->version); + superblock->block_size = lfs_fromle32(superblock->block_size); + superblock->block_count = lfs_fromle32(superblock->block_count); + superblock->name_max = lfs_fromle32(superblock->name_max); + superblock->file_max = lfs_fromle32(superblock->file_max); + superblock->attr_max = lfs_fromle32(superblock->attr_max); +} + +static void *memstr(const void *mem, size_t memsize, const char *str) +{ + const size_t findstr_len = strlen(str); + const uint8_t *memu8p = mem; + if (findstr_len > memsize) { + return NULL; + } + uint8_t *match = memchr(memu8p, str[0], memsize); + if (match != NULL) { + size_t remaining = memsize - ((uint8_t *)match - memu8p); + if (findstr_len <= remaining) { + if (memcmp(match, str, findstr_len) == 0) { + return match; + } + } + } + return NULL; +} + +int lfs_extension_read_config_from_superblock(struct lfs_config *cfg, size_t sector_size) +{ + uint8_t sect_buf[sector_size] __attribute__((aligned)); + if (!cfg->read) { + return LFS_ERR_IO; + } + lfs_superblock_t *lfs_superblock; + if (sector_size <= sizeof(*lfs_superblock)) { + return LFS_ERR_IO; + } + lfs_size_t block_size_saved = cfg->block_size; + int err = cfg->read(cfg, 0, 0, sect_buf, sector_size); + cfg->block_size = block_size_saved; + if (err) { + return err; + } + const uint8_t *ptr = memstr(sect_buf, sizeof sect_buf, "littlefs"); + if (!ptr) { + return LFS_ERR_NOENT; + } + lfs_superblock = (lfs_superblock_t *)(ptr + 12); + lfs_superblock_fromle32(lfs_superblock); + // check version + uint16_t major_version = (0xffff & (lfs_superblock->version >> 16)); + uint16_t minor_version = (0xffff & (lfs_superblock->version >> 0)); + if ((major_version != LFS_DISK_VERSION_MAJOR || minor_version > LFS_DISK_VERSION_MINOR)) { + LFS_ERROR("Invalid version v%" PRIu16 ".%" PRIu16, major_version, minor_version); + return LFS_ERR_INVAL; + } + cfg->block_size = lfs_superblock->block_size; + cfg->block_count = lfs_superblock->block_count; + return LFS_ERR_OK; +}