From 782b3c8563b2aacfe8f48a49fc6de7cbc26c4861 Mon Sep 17 00:00:00 2001 From: Felix Morgner Date: Thu, 30 Jul 2026 13:59:59 +0200 Subject: kernel: implement dev zero and null --- kernel/CMakeLists.txt | 11 +-- kernel/kapi/devices/device_registry.cpp | 10 ++- kernel/kapi/devices/error.cpp | 17 +++-- kernel/kernel/bus/pseudo.cpp | 51 ++++++++++++++ kernel/kernel/bus/pseudo.hpp | 38 +++++++++++ kernel/kernel/devices/init.cpp | 24 +++++++ kernel/kernel/devices/init.hpp | 13 ++++ kernel/kernel/devices/pseudo.cpp | 63 ++++++++++++++++++ kernel/kernel/devices/pseudo.hpp | 24 +++++++ kernel/kernel/drivers/init.cpp | 4 ++ kernel/kernel/drivers/pseudo/null.cpp | 112 +++++++++++++++++++++++++++++++ kernel/kernel/drivers/pseudo/null.hpp | 39 +++++++++++ kernel/kernel/drivers/pseudo/zero.cpp | 114 ++++++++++++++++++++++++++++++++ kernel/kernel/drivers/pseudo/zero.hpp | 39 +++++++++++ kernel/kernel/main.cpp | 68 +++++++++++++++++++ 15 files changed, 618 insertions(+), 9 deletions(-) create mode 100644 kernel/kernel/bus/pseudo.cpp create mode 100644 kernel/kernel/bus/pseudo.hpp create mode 100644 kernel/kernel/devices/init.cpp create mode 100644 kernel/kernel/devices/init.hpp create mode 100644 kernel/kernel/devices/pseudo.cpp create mode 100644 kernel/kernel/devices/pseudo.hpp create mode 100644 kernel/kernel/drivers/pseudo/null.cpp create mode 100644 kernel/kernel/drivers/pseudo/null.hpp create mode 100644 kernel/kernel/drivers/pseudo/zero.cpp create mode 100644 kernel/kernel/drivers/pseudo/zero.hpp (limited to 'kernel') diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 91075adc..3fb3bc4a 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -40,17 +40,20 @@ target_sources("kernel_lib" PRIVATE # Device Subsystem "kernel/devices/block_device_utils.cpp" + "kernel/devices/init.cpp" + "kernel/devices/pseudo.cpp" + "kernel/devices/storage.cpp" # Bus Sumbsystem "kernel/bus/boot_modules.cpp" + "kernel/bus/pseudo.cpp" "kernel/bus/root.cpp" # Driver Subsystem - "kernel/drivers/storage/ram_disk.cpp" "kernel/drivers/init.cpp" - - # Storage Device Subsystem - "kernel/devices/storage.cpp" + "kernel/drivers/pseudo/null.cpp" + "kernel/drivers/pseudo/zero.cpp" + "kernel/drivers/storage/ram_disk.cpp" # Filesystem Subsystem "kernel/filesystem/dentry.cpp" diff --git a/kernel/kapi/devices/device_registry.cpp b/kernel/kapi/devices/device_registry.cpp index 80ddde65..080ae39b 100644 --- a/kernel/kapi/devices/device_registry.cpp +++ b/kernel/kapi/devices/device_registry.cpp @@ -1,5 +1,6 @@ #include +#include #include #include @@ -48,7 +49,14 @@ namespace kapi::devices return false; } - kstd::println("[OS:DEV] Registering device {}", device->name()); + if (device->facet()) + { + kstd::println("[OS:DEV] Registering bus {}", device->name()); + } + else + { + kstd::println("[OS:DEV] Registering device {}", device->name()); + } auto added = false; { diff --git a/kernel/kapi/devices/error.cpp b/kernel/kapi/devices/error.cpp index 9d814fbe..40320551 100644 --- a/kernel/kapi/devices/error.cpp +++ b/kernel/kapi/devices/error.cpp @@ -3,7 +3,6 @@ #include #include -#include namespace kapi::devices { @@ -23,6 +22,10 @@ namespace kapi::devices { case driver_match_errc::no_match: return "driver does not match this device"; + case driver_match_errc::no_device_signature: + return "missing device signature"; + case driver_match_errc::invalid_device_signature: + return "device signature is invalid"; default: return "unknown driver matching error"; } @@ -30,11 +33,17 @@ namespace kapi::devices [[nodiscard]] auto default_error_condition(int value) const noexcept -> kstd::error_condition override { - if (value == std::to_underlying(driver_match_errc::no_match)) + switch (static_cast(value)) { - return make_error_condition(kstd::errc::not_supported); + case driver_match_errc::no_match: + case driver_match_errc::no_device_signature: + return make_error_condition(kstd::errc::not_supported); + break; + case driver_match_errc::invalid_device_signature: + return make_error_condition(kstd::errc::invalid_argument); + default: + return kstd::error_category::default_error_condition(value); } - return kstd::error_category::default_error_condition(value); } } constexpr driver_match_category_instance{}; diff --git a/kernel/kernel/bus/pseudo.cpp b/kernel/kernel/bus/pseudo.cpp new file mode 100644 index 00000000..0b002273 --- /dev/null +++ b/kernel/kernel/bus/pseudo.cpp @@ -0,0 +1,51 @@ +#include + +#include + +#include + +#include +#include + +namespace kernel::bus +{ + + namespace + { + + struct protocol final : kapi::devices::bus_protocol + { + auto enumerate(kapi::devices::bus &) -> void override + { + // Nothing to enumerate. + } + + [[nodiscard]] auto match(kapi::devices::device const & device, kapi::devices::driver const & driver) const + -> kstd::result override + { + auto signature = device.facet(); + auto claim = driver.facet(); + + if (!signature || !claim) + { + return kstd::failure(kapi::devices::driver_match_errc::no_match); + } + + auto names = claim->supported_names(); + auto found = std::ranges::find(names, signature->name()); + + if (found == claim->supported_names().end()) + { + return kstd::failure(kapi::devices::driver_match_errc::no_match); + } + + return 0u; + } + } constinit protocol_instance; + } // namespace + + pseudo::pseudo() + : kapi::devices::bus{"pseudo", protocol_instance} + {} + +} // namespace kernel::bus \ No newline at end of file diff --git a/kernel/kernel/bus/pseudo.hpp b/kernel/kernel/bus/pseudo.hpp new file mode 100644 index 00000000..dace517b --- /dev/null +++ b/kernel/kernel/bus/pseudo.hpp @@ -0,0 +1,38 @@ +#ifndef TEACHOS_KERNEL_BUS_PSEUDO_HPP +#define TEACHOS_KERNEL_BUS_PSEUDO_HPP + +#include +#include + +#include +#include +namespace kernel::bus +{ + + struct pseudo_signature + { + constexpr auto static id = kapi::capabilities::facet_id{"pseudo_signature"}; + + virtual ~pseudo_signature() = default; + + [[nodiscard]] virtual auto name() const noexcept -> std::string_view = 0; + }; + + struct pseudo_claim + { + constexpr auto static id = kapi::capabilities::facet_id{"pseudo_claim"}; + + virtual ~pseudo_claim() = default; + + [[nodiscard]] virtual auto supported_names() const noexcept -> std::span = 0; + }; + + //! The bus for all pseudo devices. + struct pseudo final : kapi::devices::bus + { + pseudo(); + }; + +} // namespace kernel::bus + +#endif \ No newline at end of file diff --git a/kernel/kernel/devices/init.cpp b/kernel/kernel/devices/init.cpp new file mode 100644 index 00000000..89f5a796 --- /dev/null +++ b/kernel/kernel/devices/init.cpp @@ -0,0 +1,24 @@ +#include + +#include +#include + +#include + +#include + +namespace kernel::devices +{ + + auto init() -> void + { + auto root = kapi::devices::get_root_bus(); + + auto pseudo_bus = kstd::make_shared(); + root->add_child(pseudo_bus); + + pseudo_bus->add_child(kstd::make_shared("null")); + pseudo_bus->add_child(kstd::make_shared("zero")); + } + +} // namespace kernel::devices \ No newline at end of file diff --git a/kernel/kernel/devices/init.hpp b/kernel/kernel/devices/init.hpp new file mode 100644 index 00000000..563e9c36 --- /dev/null +++ b/kernel/kernel/devices/init.hpp @@ -0,0 +1,13 @@ +#ifndef TEACHOS_KERNEL_DEVICES_INIT_HPP +#define TEACHOS_KERNEL_DEVICES_INIT_HPP + +#include + +namespace kernel::devices +{ + + auto init() -> void; + +} // namespace kernel::devices + +#endif \ No newline at end of file diff --git a/kernel/kernel/devices/pseudo.cpp b/kernel/kernel/devices/pseudo.cpp new file mode 100644 index 00000000..066350e8 --- /dev/null +++ b/kernel/kernel/devices/pseudo.cpp @@ -0,0 +1,63 @@ +#include + +#include + +#include +#include + +#include + +#include +#include + +namespace kernel::devices +{ + + namespace + { + struct simple_pseudo_signature final : kernel::bus::pseudo_signature + { + explicit constexpr simple_pseudo_signature(std::string_view name) + : m_name{name} + {} + + [[nodiscard]] auto name() const noexcept -> std::string_view override + { + return m_name; + } + + private: + std::string_view m_name; + }; + + constinit auto null_signature = simple_pseudo_signature{"null"}; + constinit auto zero_signature = simple_pseudo_signature{"zero"}; + constinit auto unknown_signature = simple_pseudo_signature{""}; + }; // namespace + + pseudo::pseudo(kstd::string name) + : kapi::devices::device{std::move(name)} + {} + + auto pseudo::query_facet(kapi::capabilities::facet_id facet) -> void * + { + if (facet == kernel::bus::pseudo_signature::id) + { + if (name() == "null") + { + return &null_signature; + } + else if (name() == "zero") + { + return &zero_signature; + } + else + { + return &unknown_signature; + } + } + + return device::query_facet(facet); + }; + +} // namespace kernel::devices \ No newline at end of file diff --git a/kernel/kernel/devices/pseudo.hpp b/kernel/kernel/devices/pseudo.hpp new file mode 100644 index 00000000..fb4ef2c8 --- /dev/null +++ b/kernel/kernel/devices/pseudo.hpp @@ -0,0 +1,24 @@ +#ifndef TEACHOS_KERNEL_DEVICES_PSEUDO_HPP +#define TEACHOS_KERNEL_DEVICES_PSEUDO_HPP + +#include + +#include +#include + +#include + +namespace kernel::devices +{ + + struct pseudo final : kapi::devices::device + { + explicit pseudo(kstd::string name); + + protected: + auto query_facet(kapi::capabilities::facet_id facet) -> void * override; + }; + +} // namespace kernel::devices + +#endif \ No newline at end of file diff --git a/kernel/kernel/drivers/init.cpp b/kernel/kernel/drivers/init.cpp index 766011ef..cd196fa8 100644 --- a/kernel/kernel/drivers/init.cpp +++ b/kernel/kernel/drivers/init.cpp @@ -1,5 +1,7 @@ #include +#include +#include #include #include @@ -15,6 +17,8 @@ namespace kernel::drivers auto & registry = kapi::devices::driver_registry::get(); + registry.add(kstd::make_shared()); + registry.add(kstd::make_shared()); registry.add(kstd::make_shared()); } diff --git a/kernel/kernel/drivers/pseudo/null.cpp b/kernel/kernel/drivers/pseudo/null.cpp new file mode 100644 index 00000000..d0df9000 --- /dev/null +++ b/kernel/kernel/drivers/pseudo/null.cpp @@ -0,0 +1,112 @@ +#include + +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace kstd::units_literals; +using namespace std::string_view_literals; + +namespace kernel::drivers::pseudo +{ + + namespace + { + struct null_node final : kapi::filesystem::character_special_file + { + public: + [[nodiscard]] auto read(std::span) const -> kstd::result override + { + return 0_B; + } + + auto write(std::span buffer) -> kstd::result override + { + return kstd::units::bytes{buffer.size()}; + } + }; + + constexpr auto names = std::array{"null"sv}; + } // namespace + + [[nodiscard]] auto null::probe(kapi::devices::device & device) -> kstd::result + { + auto signature = device.facet(); + if (!signature) + { + return kstd::failure(kapi::devices::driver_match_errc::no_device_signature); + } + + if (signature->name() != "null") + { + return kstd::failure(kapi::devices::driver_match_errc::invalid_device_signature); + } + + auto implementation = kstd::make_shared(); + auto published = kapi::devices::publish_facet( + device.shared_from_this(), "null", implementation.get()); + + if (!published) + { + return published; + } + + device.set_driver_data(std::move(implementation)); + + return kstd::success(); + } + + [[nodiscard]] auto null::name() const noexcept -> std::string_view + { + return "Null Source/Sink Device"; + } + + auto null::unbind(kapi::devices::device & device) -> void + { + device.set_driver_data(nullptr); + } + + auto null::claimed_major() const -> std::optional + { + return kernel::filesystem::character_major_numbers::memory; + } + + auto null::claimed_minor(kapi::devices::device & device) const -> std::optional + { + if (device.name() == "null") + { + return kernel::filesystem::character_minor_numbers::null; + } + return std::nullopt; + } + + [[nodiscard]] auto null::supported_names() const noexcept -> std::span + { + return names; + } + + auto null::query_facet(kapi::capabilities::facet_id facet) -> void * + { + if (facet == kernel::bus::pseudo_claim::id) + { + return static_cast(this); + } + + return kapi::devices::driver::query_facet(facet); + } + +} // namespace kernel::drivers::pseudo \ No newline at end of file diff --git a/kernel/kernel/drivers/pseudo/null.hpp b/kernel/kernel/drivers/pseudo/null.hpp new file mode 100644 index 00000000..f34d3a0a --- /dev/null +++ b/kernel/kernel/drivers/pseudo/null.hpp @@ -0,0 +1,39 @@ +#ifndef TEACHOS_KERNEL_DRIVERS_PSEUDO_NULL_HPP +#define TEACHOS_KERNEL_DRIVERS_PSEUDO_NULL_HPP + +#include + +#include +#include + +#include + +#include +#include +#include +#include + +namespace kernel::drivers::pseudo +{ + + struct null final : kapi::devices::driver, kernel::bus::pseudo_claim + { + [[nodiscard]] auto probe(kapi::devices::device & device) -> kstd::result override; + + auto unbind(kapi::devices::device & device) -> void override; + + [[nodiscard]] auto name() const noexcept -> std::string_view override; + + [[nodiscard]] auto claimed_major() const -> std::optional override; + + [[nodiscard]] auto claimed_minor(kapi::devices::device &) const -> std::optional override; + + [[nodiscard]] auto supported_names() const noexcept -> std::span override; + + protected: + auto query_facet(kapi::capabilities::facet_id facet) -> void * override; + }; + +} // namespace kernel::drivers::pseudo + +#endif \ No newline at end of file diff --git a/kernel/kernel/drivers/pseudo/zero.cpp b/kernel/kernel/drivers/pseudo/zero.cpp new file mode 100644 index 00000000..550a97ff --- /dev/null +++ b/kernel/kernel/drivers/pseudo/zero.cpp @@ -0,0 +1,114 @@ +#include + +#include +#include + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace kstd::units_literals; +using namespace std::string_view_literals; + +namespace kernel::drivers::pseudo +{ + + namespace + { + struct zero_node final : kapi::filesystem::character_special_file + { + public: + [[nodiscard]] auto read(std::span buffer) const -> kstd::result override + { + std::ranges::fill(buffer, std::byte{0}); + return kstd::units::bytes{buffer.size()}; + } + + auto write(std::span buffer) -> kstd::result override + { + return kstd::units::bytes{buffer.size()}; + } + }; + + constexpr auto names = std::array{"zero"sv}; + } // namespace + + [[nodiscard]] auto zero::probe(kapi::devices::device & device) -> kstd::result + { + auto signature = device.facet(); + if (!signature) + { + return kstd::failure(kapi::devices::driver_match_errc::no_device_signature); + } + + if (signature->name() != "zero") + { + return kstd::failure(kapi::devices::driver_match_errc::invalid_device_signature); + } + + auto implementation = kstd::make_shared(); + auto published = kapi::devices::publish_facet( + device.shared_from_this(), "zero", implementation.get()); + + if (!published) + { + return published; + } + + device.set_driver_data(std::move(implementation)); + + return kstd::success(); + } + + [[nodiscard]] auto zero::name() const noexcept -> std::string_view + { + return "Null-byte Source Device"; + } + + auto zero::unbind(kapi::devices::device & device) -> void + { + device.set_driver_data(nullptr); + } + + auto zero::claimed_major() const -> std::optional + { + return kernel::filesystem::character_major_numbers::memory; + } + + auto zero::claimed_minor(kapi::devices::device & device) const -> std::optional + { + if (device.name() == "zero") + { + return kernel::filesystem::character_minor_numbers::zero; + } + return std::nullopt; + } + + [[nodiscard]] auto zero::supported_names() const noexcept -> std::span + { + return names; + } + + auto zero::query_facet(kapi::capabilities::facet_id facet) -> void * + { + if (facet == kernel::bus::pseudo_claim::id) + { + return static_cast(this); + } + + return kapi::devices::driver::query_facet(facet); + } + +} // namespace kernel::drivers::pseudo \ No newline at end of file diff --git a/kernel/kernel/drivers/pseudo/zero.hpp b/kernel/kernel/drivers/pseudo/zero.hpp new file mode 100644 index 00000000..7f26cc41 --- /dev/null +++ b/kernel/kernel/drivers/pseudo/zero.hpp @@ -0,0 +1,39 @@ +#ifndef TEACHOS_KERNEL_DRIVERS_PSEUDO_ZERO_HPP +#define TEACHOS_KERNEL_DRIVERS_PSEUDO_ZERO_HPP + +#include + +#include +#include + +#include + +#include +#include +#include +#include + +namespace kernel::drivers::pseudo +{ + + struct zero final : kapi::devices::driver, kernel::bus::pseudo_claim + { + [[nodiscard]] auto probe(kapi::devices::device & device) -> kstd::result override; + + auto unbind(kapi::devices::device & device) -> void override; + + [[nodiscard]] auto name() const noexcept -> std::string_view override; + + [[nodiscard]] auto claimed_major() const -> std::optional override; + + [[nodiscard]] auto claimed_minor(kapi::devices::device &) const -> std::optional override; + + [[nodiscard]] auto supported_names() const noexcept -> std::span override; + + protected: + auto query_facet(kapi::capabilities::facet_id facet) -> void * override; + }; + +} // namespace kernel::drivers::pseudo + +#endif \ No newline at end of file diff --git a/kernel/kernel/main.cpp b/kernel/kernel/main.cpp index dc57fb55..13697eb6 100644 --- a/kernel/kernel/main.cpp +++ b/kernel/kernel/main.cpp @@ -1,4 +1,5 @@ #include "kernel/filesystem/type_registry.hpp" +#include #include #include #include @@ -141,6 +142,70 @@ auto run_demo() -> void // 14) dmp the module after create new directory and file // -exec monitor memsave 0xffffffff8025b000 0xA00000 dump_after.bin + + // 15) read from /dev/null + auto fd_5 = kapi::filesystem::open("/dev/null"); + if (fd_5) + { + kstd::println("--> successfully opened /dev/null as a file with file descriptor {}", fd_5.value()); + } + else + { + kapi::system::panic("demo failed"); + } + + auto buffer_4 = kstd::vector{10, std::byte{0xff}}; + if (auto read = kapi::filesystem::read(fd_5.value(), buffer_4); !read) + { + kapi::system::panic("demo failed: {}", read.error()); + } + else + { + bytes_read = read->value; + } + kstd::println("--> read {} bytes from /dev/null", bytes_read); + + if (auto written = kapi::filesystem::write(fd_5.value(), buffer_4); !written) + { + kapi::system::panic("demo failed: {}", written.error()); + } + else + { + bytes_written = written->value; + } + kstd::println("--> written {} bytes to /dev/null", bytes_written); + + // 16) read from /dev/null + auto fd_6 = kapi::filesystem::open("/dev/zero"); + if (fd_6) + { + kstd::println("--> successfully opened /dev/zero as a file with file descriptor {}", fd_6.value()); + } + else + { + kapi::system::panic("demo failed"); + } + + auto buffer_5 = kstd::vector{10, std::byte{0xff}}; + if (auto read = kapi::filesystem::read(fd_6.value(), buffer_5); !read) + { + kapi::system::panic("demo failed: {}", read.error()); + } + else + { + bytes_read = read->value; + } + kstd::println("--> read {} bytes from /dev/zero: {::#04x}", bytes_read, buffer_5); + + if (auto written = kapi::filesystem::write(fd_6.value(), buffer_5); !written) + { + kapi::system::panic("demo failed: {}", written.error()); + } + else + { + bytes_written = written->value; + } + kstd::println("--> written {} bytes to /dev/zero", bytes_written); } auto main() -> int @@ -162,6 +227,9 @@ auto main() -> int kernel::drivers::init(); kstd::println("[OS] Generic drivers initialized."); + kernel::devices::init(); + kstd::println("[OS] Generic devices initialized."); + kapi::devices::init_platform_drivers(); kstd::println("[OS] Platform drivers initialized."); -- cgit v1.2.3