~aleteoryx/muditaos

af960b6fac2fdd9e42072c4632ca769fce76f95f — Lucjan Bryndza 5 years ago 706321b
[EGD-5146] Add read LFS block size from part

Add littlefs block size from partition bootable offset
M board/linux/libiosyscalls/src/syscalls_posix.cpp => board/linux/libiosyscalls/src/syscalls_posix.cpp +1 -1
@@ 626,7 626,7 @@ extern "C"
    {
        if (vfs::redirect_to_image(dir)) {
            TRACE_SYSCALLN("(%s, %s, %s, %08lx, %p) -> VFS", special_file, dir, fstype, rwflag, data);
            return vfs::invoke_fs(&fs::mount, special_file, dir, fstype, rwflag);
            return vfs::invoke_fs(&fs::mount, special_file, dir, fstype, rwflag, data);
        }
        else {
            TRACE_SYSCALLN("(%s, %s, %s, %08lx,%p) -> linux fs", special_file, dir, fstype, rwflag, data);

M host-tools/genlittlefs/mklfs.c => host-tools/genlittlefs/mklfs.c +6 -0
@@ 291,6 291,12 @@ int main(int argc, char **argv)
            return EXIT_FAILURE;
        }
        free(parts);
        if (write_partition_bootunit(lopts.dst_image, lopts.partition_num, lopts.block_size)) {
            perror("Unable to write bootunit");
            free(lopts.src_dirs);
            lfs_ioaccess_close(ioctx);
            return EXIT_FAILURE;
        }
    }
    else if (lopts.mode == littlefs_opts_file) {
        int fds = open(lopts.dst_image, O_CREAT | O_WRONLY, 0644);

M host-tools/genlittlefs/parse_partitions.c => host-tools/genlittlefs/parse_partitions.c +51 -0
@@ 5,8 5,11 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

static const size_t sector_size = 512;
static const size_t part_offset = 446;
static const size_t part_size   = 16;

struct partition *find_partitions(const char *filename, part_type_t ptype, size_t *nelems)
{


@@ 61,3 64,51 @@ void print_partitions(const struct partition *part, size_t nparts)
               part[s].end / 1024);
    }
}

static inline unsigned calculate_shift(uint32_t v)
{

    static const int mult_bruijn_bit_position[32] = {0, 9,  1,  10, 13, 21, 2,  29, 11, 14, 16, 18, 22, 25, 3, 30,
                                                     8, 12, 20, 28, 15, 17, 24, 7,  19, 27, 23, 6,  26, 5,  4, 31};

    v |= v >> 1; // first round down to one less than a power of 2
    v |= v >> 2;
    v |= v >> 4;
    v |= v >> 8;
    v |= v >> 16;

    return mult_bruijn_bit_position[(uint32_t)(v * 0x07C4ACDDU) >> 27];
}

int write_partition_bootunit(const char *filename, int part_num, uint32_t block_size)
{
    if (!filename) {
        errno = EINVAL;
        return -1;
    }
    const uint8_t boot    = calculate_shift(block_size);
    const loff_t fil_offs = part_offset + (part_num - 1) * part_size;
    FILE *fil             = fopen(filename, "r+");
    if (!fil) {
        return -1;
    }
    if (fseek(fil, fil_offs, SEEK_SET) < 0) {
        fclose(fil);
        return -1;
    }
    uint8_t boot_rd;
    if (fread(&boot_rd, sizeof boot_rd, 1, fil) != 1) {
        fclose(fil);
        return -1;
    }
    if (fseek(fil, fil_offs, SEEK_SET) < 0) {
        fclose(fil);
        return -1;
    }
    uint8_t boot_wr = (boot_rd & 0x80) | (boot & 0x7f);
    if (fwrite(&boot_wr, sizeof boot_wr, 1, fil) != 1) {
        fclose(fil);
        return -1;
    }
    return fclose(fil);
}

M host-tools/genlittlefs/parse_partitions.h => host-tools/genlittlefs/parse_partitions.h +4 -0
@@ 3,6 3,8 @@

#pragma once
#include <stddef.h>
#include <stdint.h>
#include <sys/types.h>

typedef int part_type_t;



@@ 22,3 24,5 @@ struct partition *find_partitions(const char *filename, part_type_t ptype, size_
    __attribute__((nonnull(1, 3)));

void print_partitions(const struct partition *part, size_t nparts);

int write_partition_bootunit(const char *filename, int part_num, uint32_t block_size);

M module-vfs/drivers/include/purefs/fs/drivers/filesystem_littlefs.hpp => module-vfs/drivers/include/purefs/fs/drivers/filesystem_littlefs.hpp +1 -1
@@ 22,7 22,7 @@ namespace purefs::fs::drivers
         */
        auto mount_prealloc(std::shared_ptr<blkdev::internal::disk_handle> diskh, std::string_view path, unsigned flags)
            -> fsmount override;
        auto mount(fsmount mnt) noexcept -> int override;
        auto mount(fsmount mnt, const void *data) noexcept -> int override;
        auto umount(fsmount mnt) noexcept -> int override;
        auto stat_vfs(fsmount mnt, std::string_view path, statvfs &stat) const noexcept -> int override;


M module-vfs/drivers/include/purefs/fs/drivers/filesystem_vfat.hpp => module-vfs/drivers/include/purefs/fs/drivers/filesystem_vfat.hpp +1 -1
@@ 16,7 16,7 @@ namespace purefs::fs::drivers
      private:
        auto mount_prealloc(std::shared_ptr<blkdev::internal::disk_handle> diskh, std::string_view path, unsigned flags)
            -> fsmount override;
        auto mount(fsmount mnt) noexcept -> int override;
        auto mount(fsmount mnt, const void *data) noexcept -> int override;
        auto umount(fsmount mnt) noexcept -> int override;

        auto stat_vfs(fsmount mnt, std::string_view path, statvfs &stat) const noexcept -> int override;

M module-vfs/drivers/src/purefs/fs/filesystem_littlefs.cpp => module-vfs/drivers/src/purefs/fs/filesystem_littlefs.cpp +18 -8
@@ 112,11 112,21 @@ namespace
        st.st_mode    = translate_attrib_to_st_mode(fs.type, readOnly);
    }

    [[gnu::nonnull(1)]] int setup_lfs_config(lfs_config *cfg, size_t sector_size, size_t part_sectors_count)
    [[gnu::nonnull(1)]] int setup_lfs_config(lfs_config *cfg,
                                             size_t sector_size,
                                             size_t part_sectors_count,
                                             const void *data)
    {
        cfg->block_cycles   = 512;
        cfg->block_size      = c_lfs_block_size;
        cfg->block_count    = 0; // Read later from super block
        if (data) {
            // NOTE: block size from mount param
            cfg->block_size = *(reinterpret_cast<const uint32_t *>(data));
        }
        else {
            cfg->block_size = c_lfs_block_size;
            LOG_WARN("LFS: mount block size not specified using default value");
        }
        cfg->block_cycles    = 512;
        cfg->block_count     = 0; // Read later from super block
        cfg->lookahead_size  = 131072;
        const auto total_siz = uint64_t(sector_size) * uint64_t(part_sectors_count);
        if (total_siz % cfg->block_size) {


@@ 127,7 137,7 @@ namespace
        cfg->read_size  = cfg->block_size;
        cfg->prog_size  = cfg->block_size;
        cfg->cache_size = cfg->block_size;
        LOG_INFO("LFS: block_count %u sector_size %u", unsigned(cfg->block_count), unsigned(cfg->block_size));
        LOG_INFO("LFS: block count %u block size %u", unsigned(cfg->block_count), unsigned(cfg->block_size));
        return 0;
    }



@@ 207,7 217,7 @@ namespace purefs::fs::drivers
        return std::make_shared<mount_point_littlefs>(diskh, path, flags, shared_from_this());
    }

    auto filesystem_littlefs::mount(fsmount mnt) noexcept -> int
    auto filesystem_littlefs::mount(fsmount mnt, const void *data) noexcept -> int
    {
        auto disk = mnt->disk();
        if (!disk) {


@@ 232,7 242,7 @@ namespace purefs::fs::drivers
            else {
                auto sect_count = diskmm->get_info(disk, blkdev::info_type::sector_count);
                if (sect_count > 0) {
                    err = setup_lfs_config(vmnt->lfs_config(), ssize, sect_count);
                    err = setup_lfs_config(vmnt->lfs_config(), ssize, sect_count, data);
                }
                else {
                    LOG_ERROR("Unable to read sector count %i", int(sect_count));


@@ 247,7 257,7 @@ namespace purefs::fs::drivers
            LOG_ERROR("LFS mount error %i", err);
        }
        if (!err) {
            filesystem_operations::mount(mnt);
            filesystem_operations::mount(mnt, data);
        }
        else {
            littlefs::internal::remove_volume(vmnt->lfs_config());

M module-vfs/drivers/src/purefs/fs/filesystem_vfat.cpp => module-vfs/drivers/src/purefs/fs/filesystem_vfat.cpp +2 -2
@@ 148,7 148,7 @@ namespace purefs::fs::drivers
        return std::make_shared<mount_point_vfat>(diskh, path, flags, shared_from_this());
    }

    auto filesystem_vfat::mount(fsmount mnt) noexcept -> int
    auto filesystem_vfat::mount(fsmount mnt, const void *data) noexcept -> int
    {
        auto disk = mnt->disk();
        if (!disk) {


@@ 168,7 168,7 @@ namespace purefs::fs::drivers
        ret = f_mount(vmnt->fatfs(), vmnt->ff_drive(), 1);
        ret = translate_error(ret);
        if (!ret) {
            filesystem_operations::mount(mnt);
            filesystem_operations::mount(mnt, data);
        }
        return ret;
    }

R module-vfs/include/user/purefs/fs/filesystem_operations.hpp => module-vfs/include/internal/purefs/fs/filesystem_operations.hpp +4 -4
@@ 17,7 17,7 @@ namespace purefs::blkdev
        class disk_handle;
    }
    class disk_manager;
}
} // namespace purefs::blkdev

namespace purefs::fs
{


@@ 44,9 44,9 @@ namespace purefs::fs
         */
        virtual auto mount_prealloc(std::shared_ptr<blkdev::internal::disk_handle> diskh,
                                    std::string_view path,
                                    unsigned flags) -> fsmount = 0;
        virtual auto mount(fsmount mnt) noexcept -> int  = 0;
        virtual auto umount(fsmount mnt) noexcept -> int = 0;
                                    unsigned flags) -> fsmount            = 0;
        virtual auto mount(fsmount mnt, const void *data) noexcept -> int = 0;
        virtual auto umount(fsmount mnt) noexcept -> int                  = 0;
        virtual auto stat_vfs(fsmount mnt, std::string_view path, statvfs &stat) const noexcept -> int;

        /** Standard file access API */

M module-vfs/include/user/purefs/blkdev/partition.hpp => module-vfs/include/user/purefs/blkdev/partition.hpp +1 -0
@@ 16,6 16,7 @@ namespace purefs::blkdev
        sector_t start_sector{};   //! First sector
        std::size_t num_sectors{}; //! Number of sectors
        bool bootable{};           //! Partition is bootable
        unsigned char boot_unit{}; //! 7 bit boot unit field
        unsigned short type{};     //! Partition code
        std::string name;          //! Partition name in block manager
    };

M module-vfs/include/user/purefs/fs/filesystem.hpp => module-vfs/include/user/purefs/fs/filesystem.hpp +7 -2
@@ 80,13 80,18 @@ namespace purefs::fs
        auto unregister_filesystem(std::string_view fsname) -> int;

        /** Mount filesystem to the the specified mount point
         * see man(2) mount
         * @param[in] dev_or_part Device or partition for mount
         * @param[in] target Target path where the fs will be mounted
         * @param[in] flags  Mount flags
         * @param[in] data   Filesystem specific configuration
         * @return zero on success otherwise error
         */
        auto mount(std::string_view dev_or_part, std::string_view target, std::string_view fs_type, unsigned flags = 0)
            -> int;
        auto mount(std::string_view dev_or_part,
                   std::string_view target,
                   std::string_view fs_type,
                   unsigned flags   = 0,
                   const void *data = nullptr) -> int;
        /** Unmont filesystem from selected mount point
         * @param[in] mount_point Mount point where the fs is mounted
         * @return zero on success otherwise error

M module-vfs/src/newlib/vfs_io_syscalls.cpp => module-vfs/src/newlib/vfs_io_syscalls.cpp +2 -2
@@ 353,9 353,9 @@ namespace vfsn::internal::syscalls
              const char *dir,
              const char *fstype,
              unsigned long int rwflag,
              const void * /*data*/)
              const void *data)
    {
        return invoke_fs(_errno_, &purefs::fs::filesystem::mount, special_file, dir, fstype, rwflag);
        return invoke_fs(_errno_, &purefs::fs::filesystem::mount, special_file, dir, fstype, rwflag, data);
    }

} // namespace vfsn::internal::syscalls

M module-vfs/src/purefs/blkdev/partition_parser.cpp => module-vfs/src/purefs/blkdev/partition_parser.cpp +1 -0
@@ 94,6 94,7 @@ namespace purefs::blkdev::internal
        std::size_t offs = defs::ptbl_offs;
        for (auto &part : parts) {
            part.bootable     = buffer[defs::mbr_ptbl_active + offs] & 0x80;
            part.boot_unit    = buffer[defs::mbr_ptbl_active + offs] & 0x7F;
            part.type         = buffer[defs::mbr_ptbl_type + offs];
            part.num_sectors  = to_word(buffer, defs::mbr_ptbl_sect_cnt + offs);
            part.start_sector = to_word(buffer, defs::mbr_ptbl_lba + offs);

M module-vfs/src/purefs/fs/filesystem.cpp => module-vfs/src/purefs/fs/filesystem.cpp +3 -2
@@ 69,7 69,8 @@ namespace purefs::fs
    auto filesystem::mount(std::string_view dev_or_part,
                           std::string_view target,
                           std::string_view fs_type,
                           unsigned flags) -> int
                           unsigned flags,
                           const void *data) -> int
    {
        // Sanity check input data
        if (target.size() <= 1 || target[0] != '/') {


@@ 128,7 129,7 @@ namespace purefs::fs
            }
            if (diskh) {
                const auto mnt_point = vsi->second->mount_prealloc(diskh, target, flags);
                const auto ret_mnt   = vsi->second->mount(mnt_point);
                const auto ret_mnt   = vsi->second->mount(mnt_point, data);
                if (!ret_mnt) {
                    m_mounts.emplace(std::make_pair(target, mnt_point));
                    m_partitions.emplace(dev_or_part);

M module-vfs/src/purefs/fs/filesystem_operations.cpp => module-vfs/src/purefs/fs/filesystem_operations.cpp +1 -1
@@ 8,7 8,7 @@
namespace purefs::fs
{

    auto filesystem_operations::mount(fsmount mnt) noexcept -> int
    auto filesystem_operations::mount(fsmount mnt, const void *data) noexcept -> int
    {
        ++m_mount_count;
        return -ENOTSUP;

M module-vfs/src/purefs/vfs_subsystem.cpp => module-vfs/src/purefs/vfs_subsystem.cpp +14 -3
@@ 24,6 24,7 @@ namespace purefs::subsystem
        constexpr auto old_layout_part_count = 2;
        constexpr auto new_layout_part_count = 3;
        constexpr auto boot_size_limit       = 16384L;
        constexpr auto block_size_max_shift  = 21;
        namespace json
        {
            constexpr auto os_type = "ostype";


@@ 150,8 151,9 @@ namespace purefs::subsystem
            }
        }
        if (lfs_it == std::end(parts) && parts.size() == old_layout_part_count) {
            LOG_ERROR("!!!! Danger !!!! FAT partiton layout scheme. Data may be currupted when power loss.");
            LOG_WARN("Please upgrade to new partition scheme with LITTLEFS partition.");
            LOG_ERROR("!!!! Caution !!!! eMMC is formated with vFAT old layout scheme. Filesystem may be currupted on "
                      "power loss.");
            LOG_WARN("Please upgrade to new partition scheme based on the LittleFS filesystem.");
        }
        if (boot_it == std::end(parts)) {
            LOG_FATAL("Unable to find boot partition");


@@ 167,7 169,16 @@ namespace purefs::subsystem
            return err;
        }
        if (lfs_it != std::end(parts)) {
            err = vfs->mount(lfs_it->name, purefs::dir::getUserDiskPath().string(), "littlefs");
            if (lfs_it->boot_unit > block_size_max_shift) {
                LOG_FATAL("Boot sector size is out of range");
                return -ERANGE;
            }
            else {
                const uint32_t lfs_block_size = 1U << lfs_it->boot_unit;
                const auto lfs_block_size_ptr = (lfs_it->boot_unit) ? (&lfs_block_size) : nullptr;
                err                           = vfs->mount(
                    lfs_it->name, purefs::dir::getUserDiskPath().string(), "littlefs", 0, lfs_block_size_ptr);
            }
        }
        const std::string json_file = (dir::getRootDiskPath() / file::boot_json).string();
        const auto boot_dir_name    = parse_boot_json_directory(json_file);