From 62fb233eb1c0901407ef11627bb1b4a396c767a3 Mon Sep 17 00:00:00 2001 From: Bananymous Date: Wed, 29 Mar 2023 11:50:46 +0300 Subject: [PATCH] Kernel: DeviceManager is now a 'FileSystem' so it can expose devices Shell reads keyboard through /dev/input :) --- kernel/include/kernel/Device.h | 46 +++++++++++++++---- kernel/include/kernel/FS/Inode.h | 2 + kernel/include/kernel/FS/VirtualFileSystem.h | 1 + kernel/include/kernel/Input/PS2Keyboard.h | 27 ++++++++++- kernel/kernel/Device.cpp | 48 +++++++++++++++++++- kernel/kernel/FS/VirtualFileSystem.cpp | 19 ++++++-- kernel/kernel/Input/PS2Keyboard.cpp | 10 ++-- kernel/kernel/Shell.cpp | 4 +- kernel/kernel/kernel.cpp | 3 +- 9 files changed, 135 insertions(+), 25 deletions(-) diff --git a/kernel/include/kernel/Device.h b/kernel/include/kernel/Device.h index c5ca6b84f2..98e7492bc1 100644 --- a/kernel/include/kernel/Device.h +++ b/kernel/include/kernel/Device.h @@ -1,15 +1,18 @@ #pragma once +#include #include +#include +#include #include namespace Kernel { - class Device + class Device : public Inode { public: - enum class Type + enum class DeviceType { BlockDevice, CharacterDevice, @@ -17,36 +20,59 @@ namespace Kernel }; virtual ~Device() {} - virtual Type type() const = 0; + virtual DeviceType device_type() const = 0; virtual void update() {} }; class BlockDevice : public Device { public: - virtual Type type() const override { return Type::BlockDevice; } + virtual DeviceType device_type() const override { return DeviceType::BlockDevice; } }; class CharacterDevice : public Device { public: - virtual Type type() const override { return Type::CharacterDevice; } - - virtual BAN::ErrorOr read(BAN::Span); + virtual DeviceType device_type() const override { return DeviceType::CharacterDevice; } }; - class DeviceManager + class DeviceManager final : public FileSystem, public Inode { BAN_NON_COPYABLE(DeviceManager); BAN_NON_MOVABLE(DeviceManager); public: + static void initialize(); static DeviceManager& get(); void update(); void add_device(Device*); - BAN::Vector devices() { return m_devices; } + virtual ino_t ino() const override { return 0; } + virtual mode_t mode() const override { return IFDIR | IRUSR | IWUSR | IXUSR | IRGRP | IXGRP | IROTH | IXOTH; } + virtual nlink_t nlink() const override { return 0; } + virtual uid_t uid() const override { return 0; } + virtual gid_t gid() const override { return 0; } + virtual off_t size() const override { return 0; } + virtual timespec atime() const override { return { 0, 0 }; } + virtual timespec mtime() const override { return { 0, 0 }; } + virtual timespec ctime() const override { return { 0, 0 }; } + virtual blksize_t blksize() const override { return 0; } + virtual blkcnt_t blocks() const override { return 0; } + + virtual BAN::StringView name() const override { return "device-manager"sv; } + + virtual BAN::ErrorOr read(size_t, void*, size_t) override { return BAN::Error::from_errno(EISDIR); } + virtual BAN::ErrorOr create_file(BAN::StringView, mode_t) override { return BAN::Error::from_errno(EINVAL); }; + + virtual Type type() const override { return Type::DeviceManager; } + virtual bool operator==(const Inode&) const override { return false; } + + virtual BAN::RefPtr root_inode() override { return this; } + + protected: + virtual BAN::ErrorOr> read_directory_inode_impl(BAN::StringView) override; + virtual BAN::ErrorOr> read_directory_entries_impl(size_t) override; private: DeviceManager() = default; @@ -54,6 +80,8 @@ namespace Kernel private: SpinLock m_lock; BAN::Vector m_devices; + + friend class BAN::RefPtr; }; } \ No newline at end of file diff --git a/kernel/include/kernel/FS/Inode.h b/kernel/include/kernel/FS/Inode.h index 9b40b37fda..0b08ffbe52 100644 --- a/kernel/include/kernel/FS/Inode.h +++ b/kernel/include/kernel/FS/Inode.h @@ -35,6 +35,8 @@ namespace Kernel enum class Type { + DeviceManager, + Device, Ext2, }; diff --git a/kernel/include/kernel/FS/VirtualFileSystem.h b/kernel/include/kernel/FS/VirtualFileSystem.h index 86b560df7f..843becabba 100644 --- a/kernel/include/kernel/FS/VirtualFileSystem.h +++ b/kernel/include/kernel/FS/VirtualFileSystem.h @@ -19,6 +19,7 @@ namespace Kernel virtual BAN::RefPtr root_inode() override { return m_root_inode; } BAN::ErrorOr mount_test(); + BAN::ErrorOr mount(FileSystem*, BAN::StringView); struct File { diff --git a/kernel/include/kernel/Input/PS2Keyboard.h b/kernel/include/kernel/Input/PS2Keyboard.h index f6ae8f106c..53f04f1ebe 100644 --- a/kernel/include/kernel/Input/PS2Keyboard.h +++ b/kernel/include/kernel/Input/PS2Keyboard.h @@ -31,8 +31,6 @@ namespace Kernel::Input virtual void on_byte(uint8_t) override; virtual void update() override; - virtual BAN::ErrorOr read(BAN::Span) override; - private: PS2Keyboard(PS2Controller& controller) : m_controller(controller) @@ -59,6 +57,31 @@ namespace Kernel::Input PS2Keymap m_keymap; State m_state { State::Normal }; + + public: + virtual ino_t ino() const override { return 0; } + virtual mode_t mode() const override { return IFCHR | IRUSR | IRGRP; } + virtual nlink_t nlink() const override { return 0; } + virtual uid_t uid() const override { return 0; } + virtual gid_t gid() const override { return 0; } + virtual off_t size() const override { return 0; } + virtual timespec atime() const override { return { 0, 0 }; } + virtual timespec mtime() const override { return { 0, 0 }; } + virtual timespec ctime() const override { return { 0, 0 }; } + virtual blksize_t blksize() const override { return sizeof(KeyEvent); } + virtual blkcnt_t blocks() const override { return 0; } + + virtual BAN::StringView name() const override { return "input"sv; } + + virtual BAN::ErrorOr read(size_t, void*, size_t) override; + virtual BAN::ErrorOr create_file(BAN::StringView, mode_t) override { return BAN::Error::from_errno(ENOTDIR); } + + virtual Type type() const override { return Type::Device; } + virtual bool operator==(const Inode&) const override { return false; } + + protected: + virtual BAN::ErrorOr> read_directory_inode_impl(BAN::StringView) override { return BAN::Error::from_errno(ENOTDIR); } + virtual BAN::ErrorOr> read_directory_entries_impl(size_t) override { return BAN::Error::from_errno(ENOTDIR); } }; } \ No newline at end of file diff --git a/kernel/kernel/Device.cpp b/kernel/kernel/Device.cpp index 11c330159d..25db8bb87b 100644 --- a/kernel/kernel/Device.cpp +++ b/kernel/kernel/Device.cpp @@ -1,13 +1,35 @@ #include #include +#include namespace Kernel { + static DeviceManager* s_instance = nullptr; + + void DeviceManager::initialize() + { + ASSERT(s_instance == nullptr); + + s_instance = new DeviceManager; + ASSERT(s_instance != nullptr); + + MUST(Process::create_kernel( + [](void*) + { + while (true) + { + DeviceManager::get().update(); + PIT::sleep(1); + } + }, nullptr) + ); + } + DeviceManager& DeviceManager::get() { - static DeviceManager instance; - return instance; + ASSERT(s_instance); + return *s_instance; } void DeviceManager::update() @@ -23,4 +45,26 @@ namespace Kernel MUST(m_devices.push_back(device)); } + BAN::ErrorOr> DeviceManager::read_directory_inode_impl(BAN::StringView name) + { + LockGuard _(m_lock); + for (Device* device : m_devices) + if (device->name() == name) + return BAN::RefPtr(device); + return BAN::Error::from_errno(ENOENT); + } + + BAN::ErrorOr> DeviceManager::read_directory_entries_impl(size_t index) + { + BAN::Vector result; + if (index > 0) + return result; + + LockGuard _(m_lock); + TRY(result.reserve(m_devices.size())); + for (Device* device : m_devices) + TRY(result.emplace_back(device->name())); + return result; + } + } \ No newline at end of file diff --git a/kernel/kernel/FS/VirtualFileSystem.cpp b/kernel/kernel/FS/VirtualFileSystem.cpp index 22a0f5ea29..089b0c8891 100644 --- a/kernel/kernel/FS/VirtualFileSystem.cpp +++ b/kernel/kernel/FS/VirtualFileSystem.cpp @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -112,15 +113,14 @@ namespace Kernel if (!root_inode()) derrorln("Could not locate root partition"); + + TRY(mount(&DeviceManager::get(), "/dev")); + return {}; } BAN::ErrorOr VirtualFileSystem::mount_test() { - auto mount = TRY(root_inode()->read_directory_inode("mnt"sv)); - if (!mount->ifdir()) - return BAN::Error::from_errno(ENOTDIR); - for (auto* controller : m_storage_controllers) { for (auto* device : controller->devices()) @@ -130,12 +130,21 @@ namespace Kernel if (partition.name() == "mount-test"sv) { auto ext2fs = TRY(Ext2FS::create(partition)); - TRY(m_mount_points.push_back({ mount, ext2fs })); + TRY(mount(ext2fs, "/mnt"sv)); return {}; } } } } + return BAN::Error::from_c_string("Could not find mount-test partition"); + } + + BAN::ErrorOr VirtualFileSystem::mount(FileSystem* file_system, BAN::StringView path) + { + auto file = TRY(file_from_absolute_path(path)); + if (!file.inode->ifdir()) + return BAN::Error::from_errno(ENOTDIR); + TRY(m_mount_points.push_back({ file.inode, file_system })); return {}; } diff --git a/kernel/kernel/Input/PS2Keyboard.cpp b/kernel/kernel/Input/PS2Keyboard.cpp index bda81b4297..ea5511d0cd 100644 --- a/kernel/kernel/Input/PS2Keyboard.cpp +++ b/kernel/kernel/Input/PS2Keyboard.cpp @@ -226,19 +226,19 @@ namespace Kernel::Input append_command_queue(Command::SET_LEDS, new_leds); } - BAN::ErrorOr PS2Keyboard::read(BAN::Span output) + BAN::ErrorOr PS2Keyboard::read(size_t, void* buffer, size_t size) { - if (output.size() < sizeof(Input::KeyEvent)) - return BAN::Error::from_c_string("Too small buffer for KeyEvent"); + if (size < sizeof(KeyEvent)) + return BAN::Error::from_errno(ENOBUFS); while (m_event_queue.empty()) PIT::sleep(1); CriticalScope _; - *(Input::KeyEvent*)output.data() = m_event_queue.front(); + *(KeyEvent*)buffer = m_event_queue.front(); m_event_queue.pop(); - return {}; + return sizeof(KeyEvent); } } \ No newline at end of file diff --git a/kernel/kernel/Shell.cpp b/kernel/kernel/Shell.cpp index 18de43565e..37294d5db8 100644 --- a/kernel/kernel/Shell.cpp +++ b/kernel/kernel/Shell.cpp @@ -79,11 +79,13 @@ namespace Kernel void Shell::run() { + int fd = MUST(Process::current()->open("/dev/input"sv, O_RDONLY)); + TTY_PRINT("{}", m_prompt); for (;;) { Input::KeyEvent event; - MUST(((CharacterDevice*)DeviceManager::get().devices()[0])->read({ (uint8_t*)&event, sizeof(event) })); + MUST(Process::current()->read(fd, &event, sizeof(event))); key_event_callback(event); } } diff --git a/kernel/kernel/kernel.cpp b/kernel/kernel/kernel.cpp index d1c1bbcc18..922d0c3cf4 100644 --- a/kernel/kernel/kernel.cpp +++ b/kernel/kernel/kernel.cpp @@ -184,7 +184,6 @@ extern "C" void kernel_main() )))); #else MUST(scheduler.add_thread(MUST(Thread::create(init2, tty1)))); - MUST(scheduler.add_thread(MUST(Thread::create(device_updater)))); #endif scheduler.start(); ASSERT(false); @@ -206,6 +205,8 @@ void init2(void* tty1_ptr) TTY* tty1 = (TTY*)tty1_ptr; + DeviceManager::initialize(); + MUST(VirtualFileSystem::initialize()); if (auto res = VirtualFileSystem::get().mount_test(); res.is_error()) dwarnln("{}", res.error());