M enabled_unittests => enabled_unittests +1 -0
@@ 433,6 433,7 @@ TESTS_LIST["catch2-vfs-disk"]="
Boundary checks for partitions;
Disk sectors out of range for partition;
Alternative partitions in the disk manager;
+ Disk manager EEPROM emulation;
"
#---------
TESTS_LIST["catch2-vfs-littlefs"]="
M module-vfs/board/linux/purefs/include/purefs/blkdev/disk_image.hpp => module-vfs/board/linux/purefs/include/purefs/blkdev/disk_image.hpp +8 -8
@@ 5,20 5,17 @@
#include <purefs/blkdev/disk.hpp>
#include <mutex>
-#include <array>
+#include <vector>
namespace purefs::blkdev
{
class disk_image final : public disk
{
- static constexpr auto sector_size = 512UL;
static constexpr auto invalid_fd = -1;
- static constexpr auto syspart_count = 8U;
- static constexpr auto syspart_size = 256UL * 1024UL * 1024UL;
- static constexpr auto syspart_sectors = syspart_size / sector_size;
+ static constexpr auto syspart_size = 32 * 1024UL * 1024UL;
public:
- disk_image(std::string_view image_filename);
+ explicit disk_image(std::string_view image_filename, std::size_t sector_size = 512, hwpart_t num_parts = 8);
virtual ~disk_image()
{}
@@ 35,9 32,12 @@ namespace purefs::blkdev
auto open_and_truncate(hwpart_t hwpart) -> int;
private:
- std::array<int, syspart_count> m_filedes;
- std::array<unsigned long, syspart_count> m_sectors;
+ std::vector<int> m_filedes;
+ std::vector<std::size_t> m_sectors;
const std::string m_image_name;
+ const std::size_t m_sector_size;
+ const std::size_t m_syspart_sectors;
+ const hwpart_t m_sysparts;
mutable std::recursive_mutex m_mtx;
};
} // namespace purefs::blkdev
M module-vfs/board/linux/purefs/src/blkdev/disk_image.cpp => module-vfs/board/linux/purefs/src/blkdev/disk_image.cpp +21 -16
@@ 10,10 10,15 @@
namespace purefs::blkdev
{
- disk_image::disk_image(std::string_view image_filename) : m_image_name(image_filename)
+ disk_image::disk_image(std::string_view image_filename, std::size_t sector_size, hwpart_t num_parts)
+ : m_image_name(image_filename), m_sector_size(sector_size), m_syspart_sectors(syspart_size / sector_size),
+ m_sysparts(num_parts)
{
- m_filedes.fill(invalid_fd);
- std::fill(m_sectors.begin() + 1, m_sectors.end(), syspart_sectors);
+ if (num_parts < 1) {
+ throw std::range_error("Number of partitions out of range");
+ }
+ m_filedes.resize(num_parts, invalid_fd);
+ m_sectors.resize(num_parts, m_syspart_sectors);
m_sectors[0] = 0;
}
@@ 28,8 33,8 @@ namespace purefs::blkdev
if (ret < 0) {
return -errno;
}
- m_sectors[0] = fst.st_size / sector_size;
- return fst.st_size % sector_size;
+ m_sectors[0] = fst.st_size / m_sector_size;
+ return fst.st_size % m_sector_size;
}
auto disk_image::cleanup() -> int
@@ 57,11 62,11 @@ namespace purefs::blkdev
if (err) {
return err;
}
- auto offs = ::lseek64(m_filedes[hwpart], off64_t(lba) * off64_t(sector_size), SEEK_SET);
+ auto offs = ::lseek64(m_filedes[hwpart], off64_t(lba) * off64_t(m_sector_size), SEEK_SET);
if (offs < 0) {
return offs;
}
- auto to_write = count * sector_size;
+ auto to_write = count * m_sector_size;
auto buf_b = reinterpret_cast<const uint8_t *>(buf);
do {
auto ret = ::write(m_filedes[hwpart], buf_b, to_write);
@@ 76,8 81,8 @@ namespace purefs::blkdev
auto disk_image::erase(sector_t lba, std::size_t count, hwpart_t hwpart) -> int
{
- std::unique_ptr<char[]> buf(new char[count * sector_size]);
- std::memset(buf.get(), 0xff, count * sector_size);
+ std::unique_ptr<char[]> buf(new char[count * m_sector_size]);
+ std::memset(buf.get(), 0xff, count * m_sector_size);
return write(buf.get(), lba, count, hwpart);
}
@@ 91,11 96,11 @@ namespace purefs::blkdev
if (err) {
return err;
}
- auto offs = ::lseek64(m_filedes[hwpart], off64_t(lba) * off64_t(sector_size), SEEK_SET);
+ auto offs = ::lseek64(m_filedes[hwpart], off64_t(lba) * off64_t(m_sector_size), SEEK_SET);
if (offs < 0) {
return offs;
}
- auto to_read = count * sector_size;
+ auto to_read = count * m_sector_size;
auto buf_b = reinterpret_cast<uint8_t *>(buf);
do {
auto ret = ::read(m_filedes[hwpart], buf_b, to_read);
@@ 135,12 140,12 @@ namespace purefs::blkdev
auto disk_image::get_info(info_type what, hwpart_t hwpart) const -> scount_t
{
std::lock_guard<std::recursive_mutex> m_lock(m_mtx);
- if (hwpart >= syspart_count) {
+ if (hwpart >= m_sysparts) {
return -ERANGE;
}
switch (what) {
case info_type::sector_size:
- return sector_size;
+ return m_sector_size;
case info_type::sector_count:
return m_sectors[hwpart];
case info_type::erase_block:
@@ 151,12 156,12 @@ namespace purefs::blkdev
auto disk_image::range_valid(sector_t lba, std::size_t count, hwpart_t hwpart) const -> bool
{
- return (hwpart < syspart_count) && (lba < m_sectors[hwpart]) && ((lba + count) < m_sectors[hwpart]);
+ return (hwpart < m_sysparts) && (lba < m_sectors[hwpart]) && ((lba + count) <= m_sectors[hwpart]);
}
auto disk_image::disk_image::open_and_truncate(hwpart_t hwpart) -> int
{
- if (hwpart >= syspart_count) {
+ if (hwpart >= m_sysparts) {
return -ERANGE;
}
if (hwpart == 0 || m_filedes[hwpart] > 0) {
@@ 173,7 178,7 @@ namespace purefs::blkdev
if (ret < 0) {
return -errno;
}
- if (static_cast<unsigned long>(fst.st_size) < m_sectors[hwpart] * sector_size) {
+ if (static_cast<unsigned long>(fst.st_size) < m_sectors[hwpart] * m_sector_size) {
ret = ::ftruncate(m_filedes[hwpart], syspart_size);
if (ret < 0) {
return ret;
M module-vfs/board/linux/purefs/src/vfs_subsystem_internal.cpp => module-vfs/board/linux/purefs/src/vfs_subsystem_internal.cpp +8 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <purefs/vfs_subsystem_internal.hpp>
@@ 10,9 10,16 @@ namespace purefs::subsystem::internal
namespace
{
constexpr auto disk_image_name = "PurePhone.img";
+ constexpr auto eeprom_image_name = "eeprom.img";
+ static constexpr auto eeprom_sector_size = 64;
+ static constexpr auto eeprom_num_sysparts = 1;
}
auto create_default_block_device() -> std::shared_ptr<blkdev::disk>
{
return std::make_shared<blkdev::disk_image>(disk_image_name);
}
+ auto create_default_nvm_device() -> std::shared_ptr<blkdev::disk>
+ {
+ return std::make_shared<blkdev::disk_image>(eeprom_image_name, eeprom_sector_size, eeprom_num_sysparts);
+ }
} // namespace purefs::subsystem::internal
M module-vfs/board/rt1051/purefs/src/vfs_subsystem_internal.cpp => module-vfs/board/rt1051/purefs/src/vfs_subsystem_internal.cpp +5 -0
@@ 11,4 11,9 @@ namespace purefs::subsystem::internal
{
return std::make_shared<purefs::blkdev::disk_emmc>();
}
+
+ auto create_default_nvm_device() -> std::shared_ptr<blkdev::disk>
+ {
+ return {};
+ }
} // namespace purefs::subsystem::internal
M module-vfs/drivers/src/purefs/fs/filesystem_littlefs.cpp => module-vfs/drivers/src/purefs/fs/filesystem_littlefs.cpp +2 -1
@@ 18,6 18,7 @@
#include <fcntl.h>
#include <errno.h>
#include <cstring>
+#include <algorithm>
#include <sys/stat.h>
namespace
@@ 127,13 128,13 @@ namespace
}
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) {
LOG_ERROR("Block size doesn't match partition size");
return -ERANGE;
}
cfg->block_count = total_siz / cfg->block_size - 1;
+ cfg->lookahead_size = std::min<lfs_size_t>(131072, cfg->block_count);
cfg->read_size = cfg->block_size;
cfg->prog_size = cfg->block_size;
cfg->cache_size = cfg->block_size;
M module-vfs/include/internal/purefs/vfs_subsystem_internal.hpp => module-vfs/include/internal/purefs/vfs_subsystem_internal.hpp +2 -1
@@ 1,4 1,4 @@
-// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
+// Copyright (c) 2017-2021, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#pragma once
@@ 12,4 12,5 @@ namespace purefs::blkdev
namespace purefs::subsystem::internal
{
auto create_default_block_device() -> std::shared_ptr<blkdev::disk>;
+ auto create_default_nvm_device() -> std::shared_ptr<blkdev::disk>;
}
M module-vfs/include/user/purefs/blkdev/defs.hpp => module-vfs/include/user/purefs/blkdev/defs.hpp +9 -0
@@ 48,4 48,13 @@ namespace purefs::blkdev
force_suspend, //! Device is in force suspend state
power_off //! Device is in poweroff state
};
+
+ //! Disk manager flags
+ struct flags
+ {
+ enum _flags
+ {
+ no_parts_scan = 0x1 //! Don't scan partitions on disc
+ };
+ };
} // namespace purefs::blkdev
M module-vfs/src/purefs/blkdev/disk_manager.cpp => module-vfs/src/purefs/blkdev/disk_manager.cpp +8 -1
@@ 47,7 47,14 @@ namespace purefs::blkdev
return ret;
}
const auto it = m_dev_map.emplace(std::make_pair(device_name, disk));
- return reread_partitions(std::make_shared<internal::disk_handle>(disk, it.first->first));
+ if (flags & flags::no_parts_scan) {
+ disk->clear_partitions();
+ return 0;
+ }
+ else {
+ ret = reread_partitions(std::make_shared<internal::disk_handle>(disk, it.first->first));
+ return ret;
+ }
}
}
auto disk_manager::unregister_device(std::string_view device_name) -> int
M module-vfs/src/purefs/blkdev/partition_parser.cpp => module-vfs/src/purefs/blkdev/partition_parser.cpp +5 -0
@@ 28,6 28,7 @@ namespace purefs::blkdev::internal
constexpr auto reserved_sect = 0x00e;
constexpr auto number_of_fats = 0x010;
constexpr auto num_parts = 4;
+ constexpr auto min_sector_size = 512;
} // namespace
} // namespace defs
namespace
@@ 58,6 59,10 @@ namespace purefs::blkdev::internal
if (ret < 0) {
return ret;
}
+ if (sect_size < defs::min_sector_size) {
+ LOG_ERROR("Unable to scan partition when sector size < 512");
+ return -ENXIO;
+ }
// Check initial signature
if ((mbr_sect[defs::mbr_signature_offs] != 0x55) && (mbr_sect[defs::mbr_signature_offs + 1] != 0xAA)) {
LOG_ERROR("Unable to find valid partition signature");
M module-vfs/tests/unittest_disk_manager.cpp => module-vfs/tests/unittest_disk_manager.cpp +33 -1
@@ 4,6 4,7 @@
#include <catch2/catch.hpp>
#include <purefs/blkdev/disk_manager.hpp>
#include <purefs/blkdev/disk_image.hpp>
+#include <filesystem>
namespace
{
@@ 11,7 12,9 @@ namespace
constexpr auto part_disk_image = "test_disk.img";
constexpr auto part_disk_image_ext = "test_disk_ext.img";
constexpr auto part_disk_image_bad = "test_disk_bad.img";
+ constexpr auto eeprom_image = "test_eeprom.bin";
} // namespace
+
TEST_CASE("Registering and unregistering device")
{
using namespace purefs;
@@ 117,7 120,7 @@ TEST_CASE("Alternative partitions in the disk manager")
REQUIRE(sect_size > 0);
REQUIRE(sect_size == sect_size1);
const auto sect_count = dm.get_info("emmc0sys1", blkdev::info_type::sector_count);
- REQUIRE(sect_count == (256L * 1024L * 1024L) / sect_size);
+ REQUIRE(sect_count == (32 * 1024L * 1024L) / sect_size);
const auto sect_count1 = dm.get_info("emmc0", blkdev::info_type::sector_count);
REQUIRE(sect_count1 > sect_count);
std::vector<char> buf1(sect_size, 0);
@@ 136,6 139,35 @@ TEST_CASE("Alternative partitions in the disk manager")
REQUIRE(buf1 == buf2);
}
+TEST_CASE("Disk manager EEPROM emulation")
+{
+ static constexpr auto eeprom_size = 32768;
+ static constexpr auto eeprom_sector_size = 64;
+
+ using namespace purefs;
+ std::ofstream ofc(eeprom_image);
+ ofc.close();
+ std::filesystem::resize_file(eeprom_image, eeprom_size);
+ blkdev::disk_manager dm;
+ auto disk = std::make_shared<blkdev::disk_image>(eeprom_image, eeprom_sector_size, 1);
+ REQUIRE(disk);
+ REQUIRE(dm.register_device(disk, "nvrom0", blkdev::flags::no_parts_scan) == 0);
+ const auto sect_size = dm.get_info("nvrom0", blkdev::info_type::sector_size);
+ const auto sect_count = dm.get_info("nvrom0", blkdev::info_type::sector_count);
+ REQUIRE(sect_size == eeprom_sector_size);
+ REQUIRE(sect_count == eeprom_size / sect_size);
+ std::vector<char> buf_in1(sect_size, 0xAA);
+ std::vector<char> buf_in2(sect_size, 0xBB);
+ REQUIRE(dm.write("nvrom0", buf_in1.data(), 0, 1) == 0);
+ REQUIRE(dm.write("nvrom0", buf_in2.data(), sect_count - 1, 1) == 0);
+ std::vector<char> buf_out1(sect_size);
+ std::vector<char> buf_out2(sect_size);
+ REQUIRE(dm.read("nvrom0", buf_out1.data(), 0, 1) == 0);
+ REQUIRE(dm.read("nvrom0", buf_out2.data(), sect_count - 1, 1) == 0);
+ REQUIRE(buf_in1 == buf_out1);
+ REQUIRE(buf_in2 == buf_out2);
+}
+
TEST_CASE("Null pointer passed to disk manager functions")
{
using namespace purefs;