diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index 0056fd669a..ce4a8d65ea 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -46,6 +46,8 @@ set(KERNEL_SOURCES Storage/IDEController.cpp Storage/IDEChannel.cpp Storage/PATADiskDevice.cpp + Storage/RamdiskController.cpp + Storage/RamdiskDevice.cpp Storage/StorageManagement.cpp DoubleBuffer.cpp FileSystem/AnonymousFile.cpp diff --git a/Kernel/Storage/RamdiskController.cpp b/Kernel/Storage/RamdiskController.cpp new file mode 100644 index 0000000000..0841073f58 --- /dev/null +++ b/Kernel/Storage/RamdiskController.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2021, the SerenityOS developers + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include + +namespace Kernel { + +NonnullRefPtr RamdiskController::initialize() +{ + return adopt(*new RamdiskController()); +} + +bool RamdiskController::reset() +{ + TODO(); +} + +bool RamdiskController::shutdown() +{ + TODO(); +} + +size_t RamdiskController::devices_count() const +{ + return m_devices.size(); +} + +void RamdiskController::start_request(const StorageDevice&, AsyncBlockDeviceRequest&) +{ + ASSERT_NOT_REACHED(); +} + +void RamdiskController::complete_current_request(AsyncDeviceRequest::RequestResult) +{ + ASSERT_NOT_REACHED(); +} + +RamdiskController::RamdiskController() + : StorageController() +{ + // Populate ramdisk controllers from Multiboot boot modules, if any. + size_t count = 0; + for (auto used_memory_range : MemoryManager::the().used_memory_ranges()) { + if (used_memory_range.type == UsedMemoryRangeType::BootModule) { + size_t length = PAGE_ROUND_UP(used_memory_range.end.get()) - used_memory_range.start.get(); + auto region = MemoryManager::the().allocate_kernel_region(used_memory_range.start, length, "Ramdisk", Region::Access::Read | Region::Access::Write); + m_devices.append(RamdiskDevice::create(*this, move(region), 6, count)); + count++; + } + } +} + +RamdiskController::~RamdiskController() +{ +} + +RefPtr RamdiskController::device(u32 index) const +{ + if (index >= m_devices.size()) + return nullptr; + return m_devices[index]; +} + +} diff --git a/Kernel/Storage/RamdiskController.h b/Kernel/Storage/RamdiskController.h new file mode 100644 index 0000000000..a968d99356 --- /dev/null +++ b/Kernel/Storage/RamdiskController.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2021, the SerenityOS developers + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace Kernel { + +class AsyncBlockDeviceRequest; + +class RamdiskController final : public StorageController { + AK_MAKE_ETERNAL +public: +public: + static NonnullRefPtr initialize(); + virtual ~RamdiskController() override; + + virtual Type type() const override { return Type::Ramdisk; } + virtual RefPtr device(u32 index) const override; + virtual bool reset() override; + virtual bool shutdown() override; + virtual size_t devices_count() const override; + virtual void start_request(const StorageDevice&, AsyncBlockDeviceRequest&) override; + virtual void complete_current_request(AsyncDeviceRequest::RequestResult) override; + +private: + RamdiskController(); + + NonnullRefPtrVector m_devices; +}; +} diff --git a/Kernel/Storage/RamdiskDevice.cpp b/Kernel/Storage/RamdiskDevice.cpp new file mode 100644 index 0000000000..1c407f80b8 --- /dev/null +++ b/Kernel/Storage/RamdiskDevice.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2021, the SerenityOS developers + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include + +namespace Kernel { + +NonnullRefPtr RamdiskDevice::create(const RamdiskController& controller, OwnPtr&& region, int major, int minor) +{ + return adopt(*new RamdiskDevice(controller, move(region), major, minor)); +} + +RamdiskDevice::RamdiskDevice(const RamdiskController& controller, OwnPtr&& region, int major, int minor) + : StorageDevice(controller, major, minor, 512, 0) + , m_region(move(region)) +{ + klog() << "Ramdisk: Device #" << minor << " @ " << m_region->vaddr() << " length " << m_region->size(); +} + +RamdiskDevice::~RamdiskDevice() +{ +} + +const char* RamdiskDevice::class_name() const +{ + return "RamdiskDevice"; +} + +size_t RamdiskDevice::max_addressable_block() const +{ + return m_region->size() / 512; +} + +void RamdiskDevice::start_request(AsyncBlockDeviceRequest& request) +{ + LOCKER(m_lock); + + u8* base = m_region->vaddr().as_ptr(); + size_t size = m_region->size(); + u8* offset = base + request.block_index() * 512; + size_t length = request.block_count() * 512; + + if ((offset + length > base + size) || (offset + length < base)) { + request.complete(AsyncDeviceRequest::Failure); + } else { + bool success; + + if (request.request_type() == AsyncBlockDeviceRequest::Read) { + success = request.buffer().write(offset, length); + } else { + success = request.buffer().read(offset, length); + } + + request.complete(success ? AsyncDeviceRequest::Success : AsyncDeviceRequest::MemoryFault); + } +} + +} diff --git a/Kernel/Storage/RamdiskDevice.h b/Kernel/Storage/RamdiskDevice.h new file mode 100644 index 0000000000..85662769ea --- /dev/null +++ b/Kernel/Storage/RamdiskDevice.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021, the SerenityOS developers + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include +#include + +namespace Kernel { + +class RamdiskController; + +class RamdiskDevice final : public StorageDevice { + friend class RamdiskController; + AK_MAKE_ETERNAL +public: + static NonnullRefPtr create(const RamdiskController&, OwnPtr&& region, int major, int minor); + RamdiskDevice(const RamdiskController&, OwnPtr&&, int major, int minor); + virtual ~RamdiskDevice() override; + + // ^StorageDevice + virtual Type type() const override { return StorageDevice::Type::Ramdisk; } + virtual size_t max_addressable_block() const override; + + // ^BlockDevice + virtual void start_request(AsyncBlockDeviceRequest&) override; + + // ^DiskDevice + virtual const char* class_name() const override; + + bool is_slave() const; + + Lock m_lock { "RamdiskDevice" }; + + OwnPtr m_region; +}; + +} diff --git a/Kernel/Storage/StorageController.h b/Kernel/Storage/StorageController.h index fd61dc3307..8a715f1bdb 100644 --- a/Kernel/Storage/StorageController.h +++ b/Kernel/Storage/StorageController.h @@ -46,6 +46,7 @@ class StorageController : public RefCounted { AK_MAKE_ETERNAL public: enum class Type : u8 { + Ramdisk, IDE, NVMe }; diff --git a/Kernel/Storage/StorageDevice.h b/Kernel/Storage/StorageDevice.h index 1fe30c0bd2..7b284c9556 100644 --- a/Kernel/Storage/StorageDevice.h +++ b/Kernel/Storage/StorageDevice.h @@ -39,6 +39,7 @@ class StorageDevice : public BlockDevice { AK_MAKE_ETERNAL public: enum class Type : u8 { + Ramdisk, IDE, NVMe, }; diff --git a/Kernel/Storage/StorageManagement.cpp b/Kernel/Storage/StorageManagement.cpp index 0718278ab0..2d2f470e5a 100644 --- a/Kernel/Storage/StorageManagement.cpp +++ b/Kernel/Storage/StorageManagement.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include namespace Kernel { @@ -64,6 +65,7 @@ NonnullRefPtrVector StorageManagement::enumerate_controllers( controllers.append(IDEController::initialize(address, force_pio)); } }); + controllers.append(RamdiskController::initialize()); return controllers; }