aboutsummaryrefslogtreecommitdiff
path: root/kernel/src/filesystem/devfs
diff options
context:
space:
mode:
authorLukas Oesch <lukas.oesch@ost.ch>2026-06-10 10:40:46 +0200
committerLukas Oesch <lukas.oesch@ost.ch>2026-06-10 10:40:46 +0200
commit33abd5cf264cb9e34121082105b0bc17b3cf7a36 (patch)
tree36b15d53fea04f4f9d9af817100f7ad013bd9b5c /kernel/src/filesystem/devfs
parentd01caf1c4aef3c89c68b9d1cc9fe56445f0860b5 (diff)
parent7e27130c342b7299a1d2188a7192a7f17b5ac2ad (diff)
downloadkernel-33abd5cf264cb9e34121082105b0bc17b3cf7a36.tar.xz
kernel-33abd5cf264cb9e34121082105b0bc17b3cf7a36.zip
Merge branch 'develop-BA-FS26' into 'develop'HEADdevelop
Merge of BA-FS26 branch into develop See merge request teachos/kernel!49
Diffstat (limited to 'kernel/src/filesystem/devfs')
-rw-r--r--kernel/src/filesystem/devfs/filesystem.cpp81
-rw-r--r--kernel/src/filesystem/devfs/filesystem.tests.cpp72
-rw-r--r--kernel/src/filesystem/devfs/inode.cpp21
-rw-r--r--kernel/src/filesystem/devfs/inode.tests.cpp55
4 files changed, 229 insertions, 0 deletions
diff --git a/kernel/src/filesystem/devfs/filesystem.cpp b/kernel/src/filesystem/devfs/filesystem.cpp
new file mode 100644
index 0000000..ce887ff
--- /dev/null
+++ b/kernel/src/filesystem/devfs/filesystem.cpp
@@ -0,0 +1,81 @@
+#include <kernel/filesystem/devfs/filesystem.hpp>
+
+#include "kernel/filesystem/filesystem.hpp"
+#include <kernel/devices/storage/management.hpp>
+#include <kernel/filesystem/devfs/inode.hpp>
+#include <kernel/filesystem/device_inode.hpp>
+#include <kernel/filesystem/inode.hpp>
+#include <kernel/filesystem/type.hpp>
+
+#include <kapi/devices/device.hpp>
+
+#include <kstd/memory>
+
+#include <algorithm>
+#include <string_view>
+
+namespace kernel::filesystem::devfs
+{
+ struct type final : kernel::filesystem::type
+ {
+ [[nodiscard]] auto name() const noexcept -> std::string_view override
+ {
+ return "devfs";
+ }
+
+ [[nodiscard]] auto requires_device() const noexcept -> bool override
+ {
+ return false;
+ }
+
+ [[nodiscard]] auto make_instance() const -> kstd::shared_ptr<kernel::filesystem::filesystem> override
+ {
+ return kstd::make_shared<filesystem>();
+ }
+ };
+
+ [[gnu::used]]
+ constexpr auto registration = type_registration<type>{};
+
+ auto filesystem::mount(kstd::shared_ptr<kernel::filesystem::inode> const &) -> operation_result
+ {
+ m_root_inode = kstd::make_shared<inode>();
+ build_device_inode_table();
+
+ return operation_result::success;
+ }
+
+ auto filesystem::lookup(kstd::shared_ptr<kernel::filesystem::inode> const & parent, std::string_view name) const
+ -> kstd::shared_ptr<kernel::filesystem::inode>
+ {
+ if (!parent || !parent->is_directory())
+ {
+ return nullptr;
+ }
+
+ if (parent.get() != m_root_inode.get())
+ {
+ return nullptr;
+ }
+
+ auto it = std::ranges::find_if(m_inodes, [&](auto const & dev_node) {
+ if (auto device_inode_ptr = static_cast<device_inode *>(dev_node.get()))
+ {
+ return device_inode_ptr->device()->name() == name;
+ }
+ return false;
+ });
+ return (it != m_inodes.end()) ? *it : nullptr;
+ }
+
+ auto filesystem::build_device_inode_table() -> void
+ {
+ m_inodes.clear();
+
+ auto storage_mgmt = devices::storage::management::get();
+ std::ranges::for_each(storage_mgmt.all_controllers(), [&](auto const & controller) {
+ std::ranges::for_each(controller->all_devices(),
+ [&](auto const & device) { m_inodes.push_back(kstd::make_shared<device_inode>(device)); });
+ });
+ }
+} // namespace kernel::filesystem::devfs \ No newline at end of file
diff --git a/kernel/src/filesystem/devfs/filesystem.tests.cpp b/kernel/src/filesystem/devfs/filesystem.tests.cpp
new file mode 100644
index 0000000..36cb411
--- /dev/null
+++ b/kernel/src/filesystem/devfs/filesystem.tests.cpp
@@ -0,0 +1,72 @@
+#include <kernel/filesystem/devfs/filesystem.hpp>
+
+#include <kernel/filesystem/filesystem.hpp>
+#include <kernel/test_support/filesystem/storage_boot_module_fixture.hpp>
+
+#include <catch2/catch_test_macros.hpp>
+
+SCENARIO_METHOD(kernel::tests::filesystem::storage_boot_module_fixture,
+ "Devfs filesystem lookup uses storage management devices", "[filesystem][devfs][filesystem]")
+{
+ GIVEN("a boot module registry with one module")
+ {
+ setup_modules(1);
+
+ auto fs = kernel::filesystem::devfs::filesystem{};
+ auto result = fs.mount(nullptr);
+
+ THEN("mount succeeds")
+ {
+ REQUIRE(result == kernel::filesystem::filesystem::operation_result::success);
+ REQUIRE(fs.root_inode() != nullptr);
+ }
+
+ THEN("lookup on root finds ram0 device inode")
+ {
+ auto inode = fs.lookup(fs.root_inode(), "ram0");
+ REQUIRE(inode != nullptr);
+ REQUIRE(inode->is_device());
+ }
+
+ THEN("lookup of an unknown device returns null")
+ {
+ auto inode = fs.lookup(fs.root_inode(), "ram99");
+ REQUIRE(inode == nullptr);
+ }
+
+ THEN("lookup with wrong parent returns null")
+ {
+ auto other_fs = kernel::filesystem::devfs::filesystem{};
+ other_fs.mount(nullptr);
+
+ auto inode = fs.lookup(other_fs.root_inode(), "ram0");
+ REQUIRE(inode == nullptr);
+ }
+
+ THEN("lookup with a non-directory parent returns null")
+ {
+ auto non_directory_inode = fs.lookup(fs.root_inode(), "ram0");
+ REQUIRE(non_directory_inode != nullptr);
+ REQUIRE_FALSE(non_directory_inode->is_directory());
+
+ auto result = fs.lookup(non_directory_inode, "anything");
+ REQUIRE(result == nullptr);
+ }
+ }
+
+ GIVEN("a boot module registry with three modules")
+ {
+ setup_modules(3, 2048);
+
+ auto fs = kernel::filesystem::devfs::filesystem{};
+ auto result = fs.mount(nullptr);
+ REQUIRE(result == kernel::filesystem::filesystem::operation_result::success);
+
+ THEN("lookup finds all generated RAM devices")
+ {
+ REQUIRE(fs.lookup(fs.root_inode(), "ram0") != nullptr);
+ REQUIRE(fs.lookup(fs.root_inode(), "ram16") != nullptr);
+ REQUIRE(fs.lookup(fs.root_inode(), "ram32") != nullptr);
+ }
+ }
+}
diff --git a/kernel/src/filesystem/devfs/inode.cpp b/kernel/src/filesystem/devfs/inode.cpp
new file mode 100644
index 0000000..7bbfbbe
--- /dev/null
+++ b/kernel/src/filesystem/devfs/inode.cpp
@@ -0,0 +1,21 @@
+#include <kernel/filesystem/devfs/inode.hpp>
+
+#include <cstddef>
+
+namespace kernel::filesystem::devfs
+{
+ auto inode::read(void *, size_t, size_t) const -> size_t
+ {
+ return 0;
+ }
+
+ auto inode::write(void const *, size_t, size_t) -> size_t
+ {
+ return 0;
+ }
+
+ auto inode::is_directory() const -> bool
+ {
+ return true;
+ }
+} // namespace kernel::filesystem::devfs \ No newline at end of file
diff --git a/kernel/src/filesystem/devfs/inode.tests.cpp b/kernel/src/filesystem/devfs/inode.tests.cpp
new file mode 100644
index 0000000..ae26e74
--- /dev/null
+++ b/kernel/src/filesystem/devfs/inode.tests.cpp
@@ -0,0 +1,55 @@
+#include <kernel/filesystem/devfs/inode.hpp>
+
+#include <kstd/memory>
+#include <kstd/print>
+#include <kstd/vector>
+
+#include <catch2/catch_test_macros.hpp>
+
+#include <cstdint>
+
+SCENARIO("Devfs inode creation", "[filesystem][devfs][inode]")
+{
+ GIVEN("a devfs inode")
+ {
+ auto inode = kernel::filesystem::devfs::inode{};
+
+ THEN("the inode has the correct kind")
+ {
+ REQUIRE(inode.is_directory());
+ REQUIRE_FALSE(inode.is_device());
+ REQUIRE_FALSE(inode.is_regular());
+ REQUIRE_FALSE(inode.is_symbolic_link());
+ }
+ }
+}
+
+SCENARIO("Devfs inode read/write", "[filesystem][devfs][inode]")
+{
+ GIVEN("a devfs inode")
+ {
+ auto inode = kernel::filesystem::devfs::inode{};
+
+ WHEN("attempting to read from the devfs inode")
+ {
+ kstd::vector<uint8_t> buffer(512);
+ auto bytes_read = inode.read(buffer.data(), 0, buffer.size());
+
+ THEN("no bytes are read")
+ {
+ REQUIRE(bytes_read == 0);
+ }
+ }
+
+ WHEN("attempting to write to the devfs inode")
+ {
+ kstd::vector<uint8_t> buffer(512);
+ auto bytes_written = inode.write(buffer.data(), 0, buffer.size());
+
+ THEN("no bytes are written")
+ {
+ REQUIRE(bytes_written == 0);
+ }
+ }
+ }
+}