From 9ae5a230b1cd1f842c1a7c64392a0bccdba01a2d Mon Sep 17 00:00:00 2001 From: Lukas Oesch Date: Sat, 7 Mar 2026 17:04:24 +0100 Subject: implement read and write bytes from device --- kernel/filesystem/CMakeLists.txt | 6 +- .../filesystem/include/filesystem/device_file.hpp | 30 ++++++ .../include/filesystem/open_file_description.hpp | 2 + kernel/filesystem/src/device_file.cpp | 119 +++++++++++++++++++++ kernel/filesystem/src/open_file_description.cpp | 4 + 5 files changed, 160 insertions(+), 1 deletion(-) create mode 100644 kernel/filesystem/include/filesystem/device_file.hpp create mode 100644 kernel/filesystem/src/device_file.cpp (limited to 'kernel/filesystem') diff --git a/kernel/filesystem/CMakeLists.txt b/kernel/filesystem/CMakeLists.txt index 2a93c62..1d74585 100644 --- a/kernel/filesystem/CMakeLists.txt +++ b/kernel/filesystem/CMakeLists.txt @@ -3,6 +3,7 @@ add_library("kernel::filesystem" ALIAS "kernel_filesystem") target_sources("kernel_filesystem" PRIVATE "src/file.cpp" + "src/device_file.cpp" "src/open_file_description.cpp" "src/file_descriptor_table.cpp" ) @@ -12,6 +13,7 @@ target_sources("kernel_filesystem" PUBLIC BASE_DIRS "include" FILES "include/filesystem/file.hpp" + "include/filesystem/device_file.hpp" "include/filesystem/open_file_description.hpp" "include/filesystem/file_descriptor_table.hpp" ) @@ -20,6 +22,8 @@ target_include_directories("kernel_filesystem" PUBLIC "include" ) -target_link_libraries("kernel_filesystem" PRIVATE +target_link_libraries("kernel_filesystem" PUBLIC + "kernel::devices" +PRIVATE "os::kapi" ) diff --git a/kernel/filesystem/include/filesystem/device_file.hpp b/kernel/filesystem/include/filesystem/device_file.hpp new file mode 100644 index 0000000..08d81f6 --- /dev/null +++ b/kernel/filesystem/include/filesystem/device_file.hpp @@ -0,0 +1,30 @@ +#ifndef TEACH_OS_KERNEL_FILESYSTEM_DEVICE_FILE_HPP +#define TEACH_OS_KERNEL_FILESYSTEM_DEVICE_FILE_HPP + +#include "devices/block_device.hpp" +#include "devices/device.hpp" +#include "filesystem/file.hpp" + +#include + +namespace filesystem +{ + struct device_file : file + { + device_file(devices::device * device); + + auto open() -> void override; + + auto read(void * buffer, size_t offset, size_t size) const -> size_t override; + auto write(void const * buffer, size_t offset, size_t size) -> size_t override; + + private: + using block_op = void (*)(size_t idx, size_t off, size_t len, size_t done, devices::block_device * device, + std::byte * scratch, void * buffer); + auto process_blocks(size_t offset, size_t size, void * buffer, block_op op) const -> size_t; + + devices::device * m_device; + }; +} // namespace filesystem + +#endif diff --git a/kernel/filesystem/include/filesystem/open_file_description.hpp b/kernel/filesystem/include/filesystem/open_file_description.hpp index e4febbd..3241ea4 100644 --- a/kernel/filesystem/include/filesystem/open_file_description.hpp +++ b/kernel/filesystem/include/filesystem/open_file_description.hpp @@ -9,6 +9,8 @@ namespace filesystem { struct open_file_description { + open_file_description(file * file); + ~open_file_description() = default; auto read(void * buffer, size_t size) -> size_t; diff --git a/kernel/filesystem/src/device_file.cpp b/kernel/filesystem/src/device_file.cpp new file mode 100644 index 0000000..a6c234c --- /dev/null +++ b/kernel/filesystem/src/device_file.cpp @@ -0,0 +1,119 @@ +#include "filesystem/device_file.hpp" + +#include "kapi/system.hpp" + +#include "devices/block_device.hpp" +#include "devices/device.hpp" + +#include + +#include +#include +#include + +namespace filesystem +{ + device_file::device_file(devices::device * device) + : m_device(device) + { + if (m_device == nullptr) + { + kapi::system::panic("[FILESYSTEM] device_file constructed with null device."); + } + } + + auto device_file::open() -> void + { + // Hook point for permission checks or lazy metadata loading. + } + + auto device_file::read(void * buffer, size_t offset, size_t size) const -> size_t + { + if (m_device->is_block_device()) + { + return process_blocks(offset, size, buffer, + [](size_t idx, size_t off, size_t len, size_t done, devices::block_device * device, + std::byte * scratch, void * buffer) { + auto * out = static_cast(buffer); + if (off == 0 && len == device->block_size()) + { + device->read_block(idx, out + done); + } + else + { + device->read_block(idx, scratch); + kstd::libc::memcpy(out + done, scratch + off, len); + } + }); + } + else + { + kapi::system::panic("[FILESYSTEM] device_file::read called on non-block device."); + } + } + + auto device_file::write(void const * buffer, size_t offset, size_t size) -> size_t + { + if (m_device->is_block_device()) + { + return process_blocks(offset, size, const_cast(buffer), + [](size_t idx, size_t off, size_t len, size_t done, devices::block_device * device, + std::byte * scratch, void * buffer) { + auto const * in = static_cast(buffer); + if (off == 0 && len == device->block_size()) + { + device->write_block(idx, in + done); + } + else + { + device->read_block(idx, scratch); + kstd::libc::memcpy(scratch + off, in + done, len); + device->write_block(idx, scratch); + } + }); + } + else + { + kapi::system::panic("[FILESYSTEM] device_file::write called on non-block device."); + } + } + + auto device_file::process_blocks(size_t offset, size_t size, void * buffer, block_op op) const -> size_t + { + if (buffer == nullptr) + { + kapi::system::panic("[FILESYSTEM] device_file::write called with null buffer."); + } + + if (size == 0) + { + return 0; + } + + auto * block_dev = static_cast(m_device); + + size_t const block_size = block_dev->block_size(); + size_t const capacity = block_dev->capacity(); + + if (offset >= capacity) + return 0; + size_t const total_to_process = std::min(size, capacity - offset); + + std::array scratch_buffer{}; // TODO BA-FS26 better solution than fixed scratch_buffer ?? + auto processed = 0uz; + + while (processed < total_to_process) + { + size_t const absolute_offset = offset + processed; + size_t const block_index = absolute_offset / block_size; + size_t const in_block_offset = absolute_offset % block_size; + size_t const chunk_size = std::min(total_to_process - processed, block_size - in_block_offset); + + op(block_index, in_block_offset, chunk_size, processed, block_dev, scratch_buffer.data(), buffer); + + processed += chunk_size; + } + + return processed; + } +} // namespace filesystem diff --git a/kernel/filesystem/src/open_file_description.cpp b/kernel/filesystem/src/open_file_description.cpp index 8c20397..1f0410c 100644 --- a/kernel/filesystem/src/open_file_description.cpp +++ b/kernel/filesystem/src/open_file_description.cpp @@ -6,6 +6,10 @@ namespace filesystem { + open_file_description::open_file_description(file * file) + : m_file(file) + {} + auto open_file_description::read(void * buffer, size_t size) -> size_t { // TODO BA-FS26 nullptr check -- cgit v1.2.3