Kernel: Implement RamdiskDevice

This commit is contained in:
Jean-Baptiste Boric 2021-01-19 22:33:00 +01:00 committed by Andreas Kling
parent ec056f3bd1
commit 225957283e
8 changed files with 302 additions and 0 deletions

View file

@ -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

View file

@ -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 <AK/OwnPtr.h>
#include <AK/RefPtr.h>
#include <AK/Types.h>
#include <Kernel/Storage/RamdiskController.h>
namespace Kernel {
NonnullRefPtr<RamdiskController> 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<StorageDevice> RamdiskController::device(u32 index) const
{
if (index >= m_devices.size())
return nullptr;
return m_devices[index];
}
}

View file

@ -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 <AK/OwnPtr.h>
#include <AK/RefPtr.h>
#include <AK/Types.h>
#include <Kernel/Storage/RamdiskDevice.h>
#include <Kernel/Storage/StorageController.h>
#include <Kernel/Storage/StorageDevice.h>
namespace Kernel {
class AsyncBlockDeviceRequest;
class RamdiskController final : public StorageController {
AK_MAKE_ETERNAL
public:
public:
static NonnullRefPtr<RamdiskController> initialize();
virtual ~RamdiskController() override;
virtual Type type() const override { return Type::Ramdisk; }
virtual RefPtr<StorageDevice> 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<RamdiskDevice> m_devices;
};
}

View file

@ -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 <AK/Memory.h>
#include <AK/StringView.h>
#include <Kernel/FileSystem/FileDescription.h>
#include <Kernel/Storage/RamdiskController.h>
#include <Kernel/Storage/RamdiskDevice.h>
namespace Kernel {
NonnullRefPtr<RamdiskDevice> RamdiskDevice::create(const RamdiskController& controller, OwnPtr<Region>&& region, int major, int minor)
{
return adopt(*new RamdiskDevice(controller, move(region), major, minor));
}
RamdiskDevice::RamdiskDevice(const RamdiskController& controller, OwnPtr<Region>&& 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);
}
}
}

View file

@ -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 <Kernel/Lock.h>
#include <Kernel/Storage/StorageDevice.h>
namespace Kernel {
class RamdiskController;
class RamdiskDevice final : public StorageDevice {
friend class RamdiskController;
AK_MAKE_ETERNAL
public:
static NonnullRefPtr<RamdiskDevice> create(const RamdiskController&, OwnPtr<Region>&& region, int major, int minor);
RamdiskDevice(const RamdiskController&, OwnPtr<Region>&&, 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<Region> m_region;
};
}

View file

@ -46,6 +46,7 @@ class StorageController : public RefCounted<StorageController> {
AK_MAKE_ETERNAL
public:
enum class Type : u8 {
Ramdisk,
IDE,
NVMe
};

View file

@ -39,6 +39,7 @@ class StorageDevice : public BlockDevice {
AK_MAKE_ETERNAL
public:
enum class Type : u8 {
Ramdisk,
IDE,
NVMe,
};

View file

@ -32,6 +32,7 @@
#include <Kernel/Storage/Partition/EBRPartitionTable.h>
#include <Kernel/Storage/Partition/GUIDPartitionTable.h>
#include <Kernel/Storage/Partition/MBRPartitionTable.h>
#include <Kernel/Storage/RamdiskController.h>
#include <Kernel/Storage/StorageManagement.h>
namespace Kernel {
@ -64,6 +65,7 @@ NonnullRefPtrVector<StorageController> StorageManagement::enumerate_controllers(
controllers.append(IDEController::initialize(address, force_pio));
}
});
controllers.append(RamdiskController::initialize());
return controllers;
}