aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukas Oesch <lukasoesch20@gmail.com>2026-04-09 12:32:50 +0200
committerLukas Oesch <lukasoesch20@gmail.com>2026-04-11 08:05:53 +0200
commit01d5f1b29fa04c69ac9f942a1075354ce5b25da2 (patch)
treecf16f63eb2bed52e2886481c629c60a7ebf2efbf
parenta03d4d9acc5115ec3f651b06f94ced9a7c0e192f (diff)
downloadteachos-01d5f1b29fa04c69ac9f942a1075354ce5b25da2.tar.xz
teachos-01d5f1b29fa04c69ac9f942a1075354ce5b25da2.zip
add ext2 inode and filesystem tests
-rw-r--r--kernel/CMakeLists.txt3
-rw-r--r--kernel/include/kernel/filesystem/ext2/filesystem.hpp21
-rw-r--r--kernel/include/kernel/test_support/filesystem/ext2.hpp17
-rw-r--r--kernel/src/filesystem/ext2/filesystem.cpp38
-rw-r--r--kernel/src/filesystem/ext2/filesystem.tests.cpp132
-rw-r--r--kernel/src/filesystem/ext2/inode.tests.cpp159
-rw-r--r--kernel/src/test_support/filesystem/ext2.cpp62
7 files changed, 406 insertions, 26 deletions
diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt
index 88d420b..2f6113a 100644
--- a/kernel/CMakeLists.txt
+++ b/kernel/CMakeLists.txt
@@ -105,6 +105,7 @@ else()
"src/test_support/devices/character_device.cpp"
"src/test_support/filesystem/inode.cpp"
"src/test_support/filesystem/filesystem.cpp"
+ "src/test_support/filesystem/ext2.cpp"
"src/test_support/filesystem/storage_boot_module_fixture.cpp"
"src/test_support/filesystem/storage_boot_module_vfs_fixture.cpp" "src/test_support/log_buffer.cpp"
"src/test_support/output_device.cpp"
@@ -134,6 +135,8 @@ else()
# Filesystem Subsystem Tests
"src/filesystem/devfs/filesystem.tests.cpp"
"src/filesystem/devfs/inode.tests.cpp"
+ "src/filesystem/ext2/filesystem.tests.cpp"
+ "src/filesystem/ext2/inode.tests.cpp"
"src/filesystem/rootfs/filesystem.tests.cpp"
"src/filesystem/rootfs/inode.tests.cpp"
"src/filesystem/dentry.tests.cpp"
diff --git a/kernel/include/kernel/filesystem/ext2/filesystem.hpp b/kernel/include/kernel/filesystem/ext2/filesystem.hpp
index 65324c8..a71385f 100644
--- a/kernel/include/kernel/filesystem/ext2/filesystem.hpp
+++ b/kernel/include/kernel/filesystem/ext2/filesystem.hpp
@@ -19,6 +19,27 @@
namespace kernel::filesystem::ext2
{
/**
+ @brief Constants related to the ext2 filesystem.
+ */
+ namespace constants
+ {
+ constexpr size_t inline base_block_size = 1024;
+ constexpr size_t inline superblock_offset = base_block_size;
+ constexpr uint16_t inline magic_number = 0xEF53;
+
+ constexpr uint32_t inline root_inode_number = 2;
+
+ constexpr size_t inline direct_block_count = 12;
+ constexpr size_t inline singly_indirect_block_index = direct_block_count;
+ constexpr size_t inline doubly_indirect_block_index = singly_indirect_block_index + 1;
+ constexpr size_t inline triply_indirect_block_index = doubly_indirect_block_index + 1;
+
+ constexpr uint16_t inline mode_mask = 0xF000;
+ constexpr uint16_t inline mode_regular = 0x8000;
+ constexpr uint16_t inline mode_directory = 0x4000;
+ } // namespace constants
+
+ /**
@brief A filesystem implementation for the ext2 filesystem format. This class provides methods for mounting an ext2
filesystem, and looking up inodes.
*/
diff --git a/kernel/include/kernel/test_support/filesystem/ext2.hpp b/kernel/include/kernel/test_support/filesystem/ext2.hpp
new file mode 100644
index 0000000..edbda29
--- /dev/null
+++ b/kernel/include/kernel/test_support/filesystem/ext2.hpp
@@ -0,0 +1,17 @@
+#ifndef TEACHOS_KERNEL_TEST_SUPPORT_FILESYSTEM_EXT2_HPP
+#define TEACHOS_KERNEL_TEST_SUPPORT_FILESYSTEM_EXT2_HPP
+
+#include "kernel/test_support/devices/block_device.hpp"
+
+#include <cstddef>
+#include <cstdint>
+
+namespace kernel::tests::filesystem::ext2
+{
+ auto write_bytes(kernel::tests::devices::block_device & device, size_t offset, void const * source, size_t size)
+ -> void;
+ auto write_u32(kernel::tests::devices::block_device & device, size_t offset, uint32_t value) -> void;
+ auto setup_mock_ext2_layout(kernel::tests::devices::block_device & device) -> void;
+} // namespace kernel::tests::filesystem::ext2
+
+#endif \ No newline at end of file
diff --git a/kernel/src/filesystem/ext2/filesystem.cpp b/kernel/src/filesystem/ext2/filesystem.cpp
index 6d5960e..0ad5c97 100644
--- a/kernel/src/filesystem/ext2/filesystem.cpp
+++ b/kernel/src/filesystem/ext2/filesystem.cpp
@@ -21,29 +21,14 @@ namespace kernel::filesystem::ext2
{
namespace
{
- constexpr size_t SUPERBLOCK_OFFSET = 1024;
- constexpr uint16_t MAGIC_NUMBER = 0xEF53;
-
- constexpr uint32_t ROOT_INODE_NUMBER = 2;
-
- constexpr size_t DIRECT_BLOCK_COUNT = 12;
- constexpr size_t SINGLY_INDIRECT_BLOCK_INDEX = DIRECT_BLOCK_COUNT;
- constexpr size_t DOUBLY_INDIRECT_BLOCK_INDEX = SINGLY_INDIRECT_BLOCK_INDEX + 1;
- constexpr size_t TRIPLY_INDIRECT_BLOCK_INDEX = DOUBLY_INDIRECT_BLOCK_INDEX + 1;
-
- // Mode bits
- constexpr uint16_t S_IFMT = 0xF000;
- constexpr uint16_t S_IFREG = 0x8000;
- constexpr uint16_t S_IFDIR = 0x4000;
-
auto S_ISREG(uint16_t mode) -> bool
{
- return (mode & S_IFMT) == S_IFREG;
+ return (mode & constants::mode_mask) == constants::mode_regular;
}
auto S_ISDIR(uint16_t mode) -> bool
{
- return (mode & S_IFMT) == S_IFDIR;
+ return (mode & constants::mode_mask) == constants::mode_directory;
}
} // namespace
@@ -51,9 +36,10 @@ namespace kernel::filesystem::ext2
{
kernel::filesystem::filesystem::mount(device);
- kernel::devices::block_device_utils::read(m_device, &m_superblock, SUPERBLOCK_OFFSET, sizeof(m_superblock));
+ kernel::devices::block_device_utils::read(m_device, &m_superblock, constants::superblock_offset,
+ sizeof(m_superblock));
- if (m_superblock.magic != MAGIC_NUMBER)
+ if (m_superblock.magic != constants::magic_number)
{
return operation_result::invalid_magic_number;
}
@@ -69,7 +55,7 @@ namespace kernel::filesystem::ext2
block_group_descriptor_table_offset,
num_block_groups * sizeof(block_group_descriptor));
- m_root_inode = read_inode(ROOT_INODE_NUMBER);
+ m_root_inode = read_inode(constants::root_inode_number);
if (!m_root_inode || !m_root_inode->is_directory())
{
@@ -161,11 +147,11 @@ namespace kernel::filesystem::ext2
auto filesystem::map_inode_block_index_to_global_block_number(uint32_t inode_block_index, inode_data data) -> uint32_t
{
- if (inode_block_index < DIRECT_BLOCK_COUNT)
+ if (inode_block_index < constants::direct_block_count)
{
return data.block.at(inode_block_index);
}
- inode_block_index -= DIRECT_BLOCK_COUNT;
+ inode_block_index -= constants::direct_block_count;
auto const block_size = get_block_size();
auto const numbers_per_block = block_size / sizeof(uint32_t);
@@ -176,14 +162,14 @@ namespace kernel::filesystem::ext2
if (inode_block_index < block_numbers_per_singly_indirect_block)
{
- auto const singly_indirect_block_number = data.block.at(SINGLY_INDIRECT_BLOCK_INDEX);
+ auto const singly_indirect_block_number = data.block.at(constants::singly_indirect_block_index);
return read_block_number_at_index(singly_indirect_block_number, inode_block_index);
}
inode_block_index -= block_numbers_per_singly_indirect_block;
if (inode_block_index < block_numbers_per_doubly_indirect_block)
{
- auto const doubly_indirect_block_number = data.block.at(DOUBLY_INDIRECT_BLOCK_INDEX);
+ auto const doubly_indirect_block_number = data.block.at(constants::doubly_indirect_block_index);
auto const singly_indirect_block_index_in_doubly_indirect_block =
inode_block_index / block_numbers_per_singly_indirect_block;
auto const singly_indirect_block_number = read_block_number_at_index(
@@ -196,7 +182,7 @@ namespace kernel::filesystem::ext2
if (inode_block_index < block_numbers_per_triply_indirect_block)
{
- auto const triply_indirect_block_number = data.block.at(TRIPLY_INDIRECT_BLOCK_INDEX);
+ auto const triply_indirect_block_number = data.block.at(constants::triply_indirect_block_index);
auto const doubly_indirect_block_index_in_triply_indirect_block =
inode_block_index / block_numbers_per_doubly_indirect_block;
auto const doubly_indirect_block_number = read_block_number_at_index(
@@ -230,7 +216,7 @@ namespace kernel::filesystem::ext2
auto filesystem::get_block_size() -> size_t
{
- return 1024U << m_superblock.log_block_size;
+ return constants::base_block_size << m_superblock.log_block_size;
}
auto filesystem::get_inode_size() -> size_t
diff --git a/kernel/src/filesystem/ext2/filesystem.tests.cpp b/kernel/src/filesystem/ext2/filesystem.tests.cpp
new file mode 100644
index 0000000..b13ebf3
--- /dev/null
+++ b/kernel/src/filesystem/ext2/filesystem.tests.cpp
@@ -0,0 +1,132 @@
+#include "kernel/filesystem/ext2/filesystem.hpp"
+
+#include "kernel/devices/storage/management.hpp"
+#include "kernel/filesystem/ext2/inode.hpp"
+#include "kernel/filesystem/filesystem.hpp"
+#include "kernel/test_support/devices/block_device.hpp"
+#include "kernel/test_support/filesystem/ext2.hpp"
+#include "kernel/test_support/filesystem/storage_boot_module_fixture.hpp"
+
+#include <kstd/memory>
+#include <kstd/vector>
+
+#include <catch2/catch_test_macros.hpp>
+
+#include <array>
+#include <cstdint>
+#include <filesystem>
+
+SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture,
+ "Ext2 filesystem mount and lookup with real image", "[filesystem][ext2][filesystem][img]")
+{
+ auto const image_path = std::filesystem::path{KERNEL_TEST_ASSETS_DIR} / "ext2_1KB_fs.img";
+
+ GIVEN("a mounted ext2 filesystem from a real image")
+ {
+ REQUIRE(std::filesystem::exists(image_path));
+ REQUIRE_NOTHROW(setup_modules_from_img({"test_img_module"}, {image_path}));
+
+ auto boot_device = kernel::devices::storage::management::get().determine_boot_device();
+ REQUIRE(boot_device != nullptr);
+
+ auto fs = kernel::filesystem::ext2::filesystem{};
+ REQUIRE(fs.mount(boot_device) == kernel::filesystem::filesystem::operation_result::success);
+
+ THEN("the root inode is available and is a directory")
+ {
+ REQUIRE(fs.root_inode() != nullptr);
+ REQUIRE(fs.root_inode()->is_directory());
+ }
+
+ THEN("lookup resolves known entries from the image")
+ {
+ auto information = fs.lookup(fs.root_inode(), "information");
+ REQUIRE(information != nullptr);
+ REQUIRE(information->is_directory());
+
+ auto info_1 = fs.lookup(information, "info_1.txt");
+ REQUIRE(info_1 != nullptr);
+ REQUIRE(info_1->is_regular());
+ }
+
+ THEN("lookup returns null for invalid inputs")
+ {
+ REQUIRE(fs.lookup(nullptr, "information") == nullptr);
+
+ auto information = fs.lookup(fs.root_inode(), "information");
+ REQUIRE(information != nullptr);
+ auto info_1 = fs.lookup(information, "info_1.txt");
+ REQUIRE(info_1 != nullptr);
+
+ REQUIRE(fs.lookup(info_1, "anything") == nullptr);
+ REQUIRE(fs.lookup(fs.root_inode(), "does_not_exist") == nullptr);
+ }
+ }
+}
+
+SCENARIO("Ext2 filesystem rejects invalid magic", "[filesystem][ext2][filesystem]")
+{
+ auto const block_size = 1024;
+ GIVEN("a block device that does not contain an ext2 superblock")
+ {
+ auto device = kstd::make_shared<kernel::tests::devices::block_device>(0, 0, "mock", block_size, 2 * block_size);
+ REQUIRE(device != nullptr);
+
+ auto fs = kernel::filesystem::ext2::filesystem{};
+
+ THEN("mount fails with invalid_magic_number")
+ {
+ REQUIRE(fs.mount(device) == kernel::filesystem::filesystem::operation_result::invalid_magic_number);
+ }
+ }
+}
+
+SCENARIO("Ext2 block mapping includes direct and all indirect levels", "[filesystem][ext2][filesystem]")
+{
+ auto const block_size = 1024;
+
+ GIVEN("a minimally valid ext2 layout with configured indirect block tables")
+ {
+ auto device = kstd::make_shared<kernel::tests::devices::block_device>(0, 0, "mock", block_size, 128 * block_size);
+ REQUIRE(device != nullptr);
+
+ kernel::tests::filesystem::ext2::setup_mock_ext2_layout(*device);
+
+ auto fs = kernel::filesystem::ext2::filesystem{};
+ REQUIRE(fs.mount(device) == kernel::filesystem::filesystem::operation_result::success);
+
+ auto inode_data = kernel::filesystem::ext2::inode_data{};
+ inode_data.block[0] = 7;
+
+ inode_data.block[12] = 30;
+ kernel::tests::filesystem::ext2::write_u32(*device, 30 * block_size, 31);
+
+ inode_data.block[13] = 40;
+ kernel::tests::filesystem::ext2::write_u32(*device, 40 * block_size, 41);
+ kernel::tests::filesystem::ext2::write_u32(*device, 41 * block_size, 42);
+
+ inode_data.block[14] = 50;
+ kernel::tests::filesystem::ext2::write_u32(*device, 50 * block_size, 51);
+ kernel::tests::filesystem::ext2::write_u32(*device, 51 * block_size, 52);
+ kernel::tests::filesystem::ext2::write_u32(*device, 52 * block_size, 53);
+
+ auto const numbers_per_block = static_cast<uint32_t>(block_size / sizeof(uint32_t));
+ auto const singly_start = static_cast<uint32_t>(kernel::filesystem::ext2::constants::direct_block_count);
+ auto const doubly_start = singly_start + numbers_per_block;
+ auto const triply_start = doubly_start + numbers_per_block * numbers_per_block;
+
+ THEN("mapping resolves direct, singly, doubly and triply indirect indexes")
+ {
+ REQUIRE(fs.map_inode_block_index_to_global_block_number(0, inode_data) == 7);
+ REQUIRE(fs.map_inode_block_index_to_global_block_number(singly_start, inode_data) == 31);
+ REQUIRE(fs.map_inode_block_index_to_global_block_number(doubly_start, inode_data) == 42);
+ REQUIRE(fs.map_inode_block_index_to_global_block_number(triply_start, inode_data) == 53);
+ }
+
+ THEN("mapping returns zero for out-of-range indexes")
+ {
+ auto const beyond_triply = triply_start + numbers_per_block * numbers_per_block * numbers_per_block;
+ REQUIRE(fs.map_inode_block_index_to_global_block_number(beyond_triply, inode_data) == 0);
+ }
+ }
+}
diff --git a/kernel/src/filesystem/ext2/inode.tests.cpp b/kernel/src/filesystem/ext2/inode.tests.cpp
new file mode 100644
index 0000000..795ff10
--- /dev/null
+++ b/kernel/src/filesystem/ext2/inode.tests.cpp
@@ -0,0 +1,159 @@
+#include "kernel/filesystem/ext2/inode.hpp"
+
+#include "kernel/devices/storage/management.hpp"
+#include "kernel/filesystem/ext2/filesystem.hpp"
+#include "kernel/filesystem/filesystem.hpp"
+#include "kernel/test_support/cpu.hpp"
+#include "kernel/test_support/devices/block_device.hpp"
+#include "kernel/test_support/filesystem/ext2.hpp"
+#include "kernel/test_support/filesystem/storage_boot_module_fixture.hpp"
+
+#include <kstd/memory>
+#include <kstd/vector>
+
+#include <catch2/catch_test_macros.hpp>
+
+#include <cstddef>
+#include <filesystem>
+#include <string_view>
+
+SCENARIO("Ext2 inode initialization and properties", "[filesystem][ext2][inode]")
+{
+ GIVEN("an ext2 filesystem")
+ {
+ auto fs = kernel::filesystem::ext2::filesystem{};
+
+ THEN("the inode is initialized and has the kind regular")
+ {
+ auto inode = kernel::filesystem::ext2::inode{&fs};
+ REQUIRE(inode.is_regular());
+ REQUIRE(!inode.is_directory());
+ REQUIRE(!inode.is_device());
+ }
+ }
+
+ GIVEN("no filesystem (null pointer)")
+ {
+ THEN("constructing an inode with a null filesystem pointer panics")
+ {
+ REQUIRE_THROWS_AS(kernel::filesystem::ext2::inode{nullptr}, kernel::tests::cpu::halt);
+ }
+ }
+}
+
+SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture, "Ext2 inode reads from real image",
+ "[filesystem][ext2][inode][img]")
+{
+ auto const image_path = std::filesystem::path{KERNEL_TEST_ASSETS_DIR} / "ext2_1KB_fs.img";
+
+ GIVEN("a mounted ext2 filesystem and a regular file inode")
+ {
+ REQUIRE(std::filesystem::exists(image_path));
+ REQUIRE_NOTHROW(setup_modules_from_img({"test_img_module"}, {image_path}));
+
+ auto boot_device = kernel::devices::storage::management::get().determine_boot_device();
+ REQUIRE(boot_device != nullptr);
+
+ auto fs = kernel::filesystem::ext2::filesystem{};
+ REQUIRE(fs.mount(boot_device) == kernel::filesystem::filesystem::operation_result::success);
+
+ auto information = fs.lookup(fs.root_inode(), "information");
+ REQUIRE(information != nullptr);
+ auto file = fs.lookup(information, "info_1.txt");
+ REQUIRE(file != nullptr);
+ REQUIRE(file->is_regular());
+
+ THEN("reading from offset zero returns expected file prefix")
+ {
+ auto buffer = kstd::vector<std::byte>(6);
+ auto const bytes_read = file->read(buffer.data(), 0, buffer.size());
+
+ REQUIRE(bytes_read == 6);
+
+ auto const text = std::string_view{reinterpret_cast<char const *>(buffer.data()), bytes_read};
+ REQUIRE(text == "info_1");
+ }
+
+ THEN("reading with an offset returns the expected byte")
+ {
+ auto buffer = kstd::vector<std::byte>(1);
+ auto const bytes_read = file->read(buffer.data(), 5, buffer.size());
+
+ REQUIRE(bytes_read == 1);
+ REQUIRE(static_cast<char>(buffer[0]) == '1');
+ }
+ }
+}
+
+SCENARIO("Ext2 inode read stops when block mapping resolves to zero", "[filesystem][ext2][inode]")
+{
+ auto const block_size = 1024;
+ GIVEN("an ext2 inode without mapped data blocks")
+ {
+ auto device = kstd::make_shared<kernel::tests::devices::block_device>(0, 0, "mock", block_size, 64 * block_size);
+ REQUIRE(device != nullptr);
+ kernel::tests::filesystem::ext2::setup_mock_ext2_layout(*device);
+
+ auto fs = kernel::filesystem::ext2::filesystem{};
+ REQUIRE(fs.mount(device) == kernel::filesystem::filesystem::operation_result::success);
+
+ auto inode = kernel::filesystem::ext2::inode{&fs};
+ inode.m_data.blocks = 2;
+ inode.m_data.block[0] = 0;
+
+ auto buffer = kstd::vector<std::byte>(32, std::byte{0xAB});
+
+ THEN("no bytes are read")
+ {
+ auto const bytes_read = inode.read(buffer.data(), 0, buffer.size());
+ REQUIRE(bytes_read == 0);
+ }
+ }
+}
+
+SCENARIO("Ext2 inode read across block boundaries", "[filesystem][ext2][inode]")
+{
+ auto const block_size = 1024;
+ GIVEN("an ext2 inode with two direct blocks and a block size of 1024 bytes")
+ {
+ auto device = kstd::make_shared<kernel::tests::devices::block_device>(0, 0, "mock", block_size, 64 * block_size);
+ REQUIRE(device != nullptr);
+ kernel::tests::filesystem::ext2::setup_mock_ext2_layout(*device);
+
+ auto fs = kernel::filesystem::ext2::filesystem{};
+ REQUIRE(fs.mount(device) == kernel::filesystem::filesystem::operation_result::success);
+
+ auto inode = kernel::filesystem::ext2::inode{&fs};
+ inode.m_data.blocks = 2;
+ inode.m_data.block[0] = 20;
+ kernel::tests::filesystem::ext2::write_bytes(*device, 21 * block_size - 6, "Hello ", 6);
+ inode.m_data.block[1] = 21;
+ kernel::tests::filesystem::ext2::write_bytes(*device, 21 * block_size, "World!", 6);
+
+ auto buffer = kstd::vector<std::byte>(12, std::byte{0x00});
+
+ THEN("reading across the block boundary returns the combined content")
+ {
+ auto const bytes_read = inode.read(buffer.data(), block_size - 6, buffer.size());
+ REQUIRE(bytes_read == 12);
+
+ auto const text = std::string_view{reinterpret_cast<char const *>(buffer.data()), bytes_read};
+ REQUIRE(text == "Hello World!");
+ }
+ }
+}
+
+SCENARIO("Ext2 inode write is not implemented", "[filesystem][ext2][inode]")
+{
+ GIVEN("an ext2 inode")
+ {
+ auto fs = kernel::filesystem::ext2::filesystem{};
+ auto inode = kernel::filesystem::ext2::inode{&fs};
+
+ THEN("writing to the inode panics")
+ {
+ auto buffer = kstd::vector<std::byte>(32, std::byte{0x00});
+ REQUIRE_THROWS_AS(inode.write(buffer.data(), 0, buffer.size()), kernel::tests::cpu::halt);
+ }
+ }
+}
diff --git a/kernel/src/test_support/filesystem/ext2.cpp b/kernel/src/test_support/filesystem/ext2.cpp
new file mode 100644
index 0000000..3627373
--- /dev/null
+++ b/kernel/src/test_support/filesystem/ext2.cpp
@@ -0,0 +1,62 @@
+#include "kernel/test_support/filesystem/ext2.hpp"
+
+#include "kernel/filesystem/ext2/block_group_descriptor.hpp"
+#include "kernel/filesystem/ext2/filesystem.hpp"
+#include "kernel/filesystem/ext2/inode.hpp"
+#include "kernel/filesystem/ext2/superblock.hpp"
+#include "kernel/test_support/devices/block_device.hpp"
+
+#include <cstdint>
+#include <cstring>
+
+namespace kernel::tests::filesystem::ext2
+{
+ namespace
+ {
+ constexpr uint32_t root_directory_data_block = 20;
+ } // namespace
+
+ auto write_bytes(kernel::tests::devices::block_device & device, size_t offset, void const * source, size_t size)
+ -> void
+ {
+ auto const required_size = offset + size;
+ if (device.data.size() < required_size)
+ {
+ device.data.resize(required_size, 0);
+ }
+
+ std::memcpy(device.data.data() + offset, source, size);
+ }
+
+ auto write_u32(kernel::tests::devices::block_device & device, size_t offset, uint32_t value) -> void
+ {
+ write_bytes(device, offset, &value, sizeof(value));
+ }
+
+ auto setup_mock_ext2_layout(kernel::tests::devices::block_device & device) -> void
+ {
+ auto superblock = kernel::filesystem::ext2::superblock{};
+ superblock.magic = kernel::filesystem::ext2::constants::magic_number;
+ superblock.log_block_size = 0;
+ superblock.blocks_count = 64;
+ superblock.blocks_per_group = 64;
+ superblock.inodes_per_group = 32;
+ superblock.rev_level = 1;
+ superblock.inode_size = 128;
+ write_bytes(device, kernel::filesystem::ext2::constants::superblock_offset, &superblock, sizeof(superblock));
+
+ auto group_descriptor = kernel::filesystem::ext2::block_group_descriptor{};
+ group_descriptor.inode_table = 5;
+ write_bytes(device, 2048, &group_descriptor, sizeof(group_descriptor));
+
+ auto root_inode_data = kernel::filesystem::ext2::inode_data{};
+ root_inode_data.mode = kernel::filesystem::ext2::constants::mode_directory;
+ root_inode_data.blocks = 2;
+ root_inode_data.block[0] = root_directory_data_block;
+
+ auto const root_inode_offset =
+ static_cast<size_t>(group_descriptor.inode_table) * kernel::filesystem::ext2::constants::base_block_size +
+ (kernel::filesystem::ext2::constants::root_inode_number - 1) * superblock.inode_size;
+ write_bytes(device, root_inode_offset, &root_inode_data, sizeof(root_inode_data));
+ }
+} // namespace kernel::tests::filesystem::ext2 \ No newline at end of file