diff --git a/kernel/CMakeLists.txt b/kernel/CMakeLists.txt index 450bdddf..3ad1ac24 100644 --- a/kernel/CMakeLists.txt +++ b/kernel/CMakeLists.txt @@ -59,6 +59,7 @@ set(KERNEL_SOURCES kernel/Storage/ATA/ATAController.cpp kernel/Storage/ATA/ATADevice.cpp kernel/Storage/DiskCache.cpp + kernel/Storage/Partition.cpp kernel/Storage/StorageDevice.cpp kernel/Syscall.cpp kernel/Syscall.S diff --git a/kernel/include/kernel/Storage/Partition.h b/kernel/include/kernel/Storage/Partition.h new file mode 100644 index 00000000..8316f142 --- /dev/null +++ b/kernel/include/kernel/Storage/Partition.h @@ -0,0 +1,50 @@ +#pragma once + +#include +#include + +namespace Kernel +{ + + class Partition final : public BlockDevice + { + public: + static BAN::ErrorOr> create(BAN::RefPtr, const BAN::GUID& type, const BAN::GUID& guid, uint64_t first_sector, uint64_t last_sector, uint64_t attr, const char* label, uint32_t index); + + const BAN::GUID& partition_type() const { return m_type; } + const BAN::GUID& partition_guid() const { return m_guid; } + const BAN::RefPtr device() const { return m_device; } + + virtual blksize_t blksize() const { return m_device->blksize(); } + + virtual BAN::ErrorOr read_sectors(uint64_t first_sector, size_t sector_count, BAN::ByteSpan) override; + virtual BAN::ErrorOr write_sectors(uint64_t first_sector, size_t sector_count, BAN::ConstByteSpan) override; + + virtual BAN::StringView name() const override { return m_name; } + + private: + Partition(BAN::RefPtr, const BAN::GUID&, const BAN::GUID&, uint64_t, uint64_t, uint64_t, const char*, uint32_t); + + private: + BAN::RefPtr m_device; + const BAN::GUID m_type; + const BAN::GUID m_guid; + const uint64_t m_first_sector; + const uint64_t m_last_sector; + const uint64_t m_attributes; + char m_label[36 * 4 + 1]; + const BAN::String m_name; + + public: + virtual bool is_partition() const override { return true; } + + virtual dev_t rdev() const override { return m_rdev; } + + protected: + virtual BAN::ErrorOr read_impl(off_t, BAN::ByteSpan) override; + + private: + const dev_t m_rdev; + }; + +} diff --git a/kernel/include/kernel/Storage/StorageDevice.h b/kernel/include/kernel/Storage/StorageDevice.h index 49f6a8aa..a5efac6f 100644 --- a/kernel/include/kernel/Storage/StorageDevice.h +++ b/kernel/include/kernel/Storage/StorageDevice.h @@ -3,63 +3,11 @@ #include #include #include +#include namespace Kernel { - struct GUID - { - uint32_t data1; - uint16_t data2; - uint16_t data3; - uint8_t data4[8]; - }; - - class StorageDevice; - - class Partition final : public BlockDevice - { - public: - static BAN::ErrorOr> create(StorageDevice&, const GUID& type, const GUID& guid, uint64_t start, uint64_t end, uint64_t attr, const char* label, uint32_t index); - - const GUID& partition_type() const { return m_type; } - const GUID& partition_guid() const { return m_guid; } - uint64_t lba_start() const { return m_lba_start; } - uint64_t lba_end() const { return m_lba_end; } - uint64_t attributes() const { return m_attributes; } - const char* label() const { return m_label; } - const StorageDevice& device() const { return m_device; } - - BAN::ErrorOr read_sectors(uint64_t lba, uint8_t sector_count, BAN::ByteSpan); - BAN::ErrorOr write_sectors(uint64_t lba, uint8_t sector_count, BAN::ConstByteSpan); - - virtual BAN::StringView name() const override { return m_name; } - - private: - Partition(StorageDevice&, const GUID&, const GUID&, uint64_t, uint64_t, uint64_t, const char*, uint32_t); - - private: - StorageDevice& m_device; - const GUID m_type; - const GUID m_guid; - const uint64_t m_lba_start; - const uint64_t m_lba_end; - const uint64_t m_attributes; - char m_label[36 * 4 + 1]; - const BAN::String m_name; - - public: - virtual bool is_partition() const override { return true; } - - virtual dev_t rdev() const override { return m_rdev; } - - protected: - virtual BAN::ErrorOr read_impl(off_t, BAN::ByteSpan) override; - - private: - const dev_t m_rdev; - }; - class StorageDevice : public BlockDevice { public: @@ -70,8 +18,8 @@ namespace Kernel BAN::ErrorOr initialize_partitions(); - BAN::ErrorOr read_sectors(uint64_t lba, uint64_t sector_count, BAN::ByteSpan); - BAN::ErrorOr write_sectors(uint64_t lba, uint64_t sector_count, BAN::ConstByteSpan); + BAN::ErrorOr read_sectors(uint64_t lba, size_t sector_count, BAN::ByteSpan); + BAN::ErrorOr write_sectors(uint64_t lba, size_t sector_count, BAN::ConstByteSpan); virtual uint32_t sector_size() const = 0; virtual uint64_t total_size() const = 0; diff --git a/kernel/kernel/Storage/Partition.cpp b/kernel/kernel/Storage/Partition.cpp new file mode 100644 index 00000000..ccaa28bc --- /dev/null +++ b/kernel/kernel/Storage/Partition.cpp @@ -0,0 +1,70 @@ +#include + +#include + +namespace Kernel +{ + + BAN::ErrorOr> Partition::create(BAN::RefPtr device, const BAN::GUID& type, const BAN::GUID& guid, uint64_t first_sector, uint64_t last_sector, uint64_t attr, const char* label, uint32_t index) + { + auto partition_ptr = new Partition(device, type, guid, first_sector, last_sector, attr, label, index); + if (partition_ptr == nullptr) + return BAN::Error::from_errno(ENOMEM); + return BAN::RefPtr::adopt(partition_ptr); + } + + Partition::Partition(BAN::RefPtr device, const BAN::GUID& type, const BAN::GUID& guid, uint64_t first_sector, uint64_t last_sector, uint64_t attr, const char* label, uint32_t index) + : BlockDevice(0660, 0, 0) + , m_device(device) + , m_type(type) + , m_guid(guid) + , m_first_sector(first_sector) + , m_last_sector(last_sector) + , m_attributes(attr) + , m_name(BAN::String::formatted("{}{}", device->name(), index)) + , m_rdev(makedev(major(device->rdev()), index)) + { + memcpy(m_label, label, sizeof(m_label)); + } + + BAN::ErrorOr Partition::read_sectors(uint64_t first_sector, size_t sector_count, BAN::ByteSpan buffer) + { + ASSERT(buffer.size() >= sector_count * m_device->blksize()); + const uint32_t sectors_in_partition = m_last_sector - m_first_sector + 1; + if (first_sector + sector_count > sectors_in_partition) + return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries); + TRY(m_device->read_sectors(m_first_sector + first_sector, sector_count, buffer)); + return {}; + } + + BAN::ErrorOr Partition::write_sectors(uint64_t first_sector, size_t sector_count, BAN::ConstByteSpan buffer) + { + ASSERT(buffer.size() >= sector_count * m_device->blksize()); + const uint32_t sectors_in_partition = m_last_sector - m_first_sector + 1; + if (m_first_sector + sector_count > sectors_in_partition) + return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries); + TRY(m_device->write_sectors(m_first_sector + first_sector, sector_count, buffer)); + return {}; + } + + BAN::ErrorOr Partition::read_impl(off_t offset, BAN::ByteSpan buffer) + { + ASSERT(offset >= 0); + + if (offset % m_device->blksize() || buffer.size() % m_device->blksize()) + return BAN::Error::from_errno(ENOTSUP); + + const uint32_t sectors_in_partition = m_last_sector - m_first_sector + 1; + uint32_t first_sector = offset / m_device->blksize(); + uint32_t sector_count = buffer.size() / m_device->blksize(); + + if (first_sector >= sectors_in_partition) + return 0; + if (first_sector + sector_count > sectors_in_partition) + sector_count = sectors_in_partition - first_sector; + + TRY(read_sectors(first_sector, sector_count, buffer)); + return sector_count * m_device->blksize(); + } + +} diff --git a/kernel/kernel/Storage/StorageDevice.cpp b/kernel/kernel/Storage/StorageDevice.cpp index 583a3a0b..cd6c86e3 100644 --- a/kernel/kernel/Storage/StorageDevice.cpp +++ b/kernel/kernel/Storage/StorageDevice.cpp @@ -9,12 +9,6 @@ #include #include -#include - -#define ATA_DEVICE_PRIMARY 0x1F0 -#define ATA_DEVICE_SECONDARY 0x170 -#define ATA_DEVICE_SLAVE_BIT 0x10 - namespace Kernel { @@ -29,7 +23,7 @@ namespace Kernel BAN::LittleEndian alternate_lba; BAN::LittleEndian first_usable_lba; BAN::LittleEndian last_usable_lba; - GUID disk_guid; + BAN::GUID disk_guid; BAN::LittleEndian partition_entry_lba; BAN::LittleEndian partition_entry_count; BAN::LittleEndian partition_entry_size; @@ -38,8 +32,8 @@ namespace Kernel struct PartitionEntry { - GUID partition_type_guid; - GUID unique_partition_guid; + BAN::GUID partition_type_guid; + BAN::GUID unique_partition_guid; BAN::LittleEndian starting_lba; BAN::LittleEndian ending_lba; BAN::LittleEndian attributes; @@ -180,15 +174,15 @@ namespace Kernel { const PartitionEntry& entry = *(const PartitionEntry*)(entry_array.data() + header.partition_entry_size * i); - GUID zero {}; - if (memcmp(&entry.partition_type_guid, &zero, sizeof(GUID)) == 0) + BAN::GUID zero {}; + if (memcmp(&entry.partition_type_guid, &zero, sizeof(BAN::GUID)) == 0) continue; char utf8_name[36 * 4 + 1]; BAN::UTF8::from_codepoints(entry.partition_name, 36, utf8_name); auto partition = TRY(Partition::create( - *this, + this, entry.partition_type_guid, entry.unique_partition_guid, entry.starting_lba, @@ -206,68 +200,6 @@ namespace Kernel return {}; } - BAN::ErrorOr> Partition::create(StorageDevice& device, const GUID& type, const GUID& guid, uint64_t start, uint64_t end, uint64_t attr, const char* label, uint32_t index) - { - auto partition_ptr = new Partition(device, type, guid, start, end, attr, label, index); - if (partition_ptr == nullptr) - return BAN::Error::from_errno(ENOMEM); - return BAN::RefPtr::adopt(partition_ptr); - } - - Partition::Partition(StorageDevice& device, const GUID& type, const GUID& guid, uint64_t start, uint64_t end, uint64_t attr, const char* label, uint32_t index) - : BlockDevice(0660, 0, 0) - , m_device(device) - , m_type(type) - , m_guid(guid) - , m_lba_start(start) - , m_lba_end(end) - , m_attributes(attr) - , m_name(BAN::String::formatted("{}{}", device.name(), index)) - , m_rdev(makedev(major(device.rdev()), index)) - { - memcpy(m_label, label, sizeof(m_label)); - } - - BAN::ErrorOr Partition::read_sectors(uint64_t lba, uint8_t sector_count, BAN::ByteSpan buffer) - { - ASSERT(buffer.size() >= sector_count * m_device.sector_size()); - const uint32_t sectors_in_partition = m_lba_end - m_lba_start; - if (lba + sector_count > sectors_in_partition) - return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries); - TRY(m_device.read_sectors(m_lba_start + lba, sector_count, buffer)); - return {}; - } - - BAN::ErrorOr Partition::write_sectors(uint64_t lba, uint8_t sector_count, BAN::ConstByteSpan buffer) - { - ASSERT(buffer.size() >= sector_count * m_device.sector_size()); - const uint32_t sectors_in_partition = m_lba_end - m_lba_start; - if (lba + sector_count > sectors_in_partition) - return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries); - TRY(m_device.write_sectors(m_lba_start + lba, sector_count, buffer)); - return {}; - } - - BAN::ErrorOr Partition::read_impl(off_t offset, BAN::ByteSpan buffer) - { - ASSERT(offset >= 0); - - if (offset % m_device.sector_size() || buffer.size() % m_device.sector_size()) - return BAN::Error::from_errno(ENOTSUP); - - const uint32_t sectors_in_partition = m_lba_end - m_lba_start; - uint32_t lba = offset / m_device.sector_size(); - uint32_t sector_count = buffer.size() / m_device.sector_size(); - - if (lba == sectors_in_partition) - return 0; - if (lba + sector_count > sectors_in_partition) - sector_count = sectors_in_partition - lba; - - TRY(read_sectors(lba, sector_count, buffer)); - return sector_count * m_device.sector_size(); - } - StorageDevice::~StorageDevice() { } @@ -287,7 +219,7 @@ namespace Kernel return {}; } - BAN::ErrorOr StorageDevice::read_sectors(uint64_t lba, uint64_t sector_count, BAN::ByteSpan buffer) + BAN::ErrorOr StorageDevice::read_sectors(uint64_t lba, size_t sector_count, BAN::ByteSpan buffer) { ASSERT(buffer.size() >= sector_count * sector_size()); @@ -313,7 +245,7 @@ namespace Kernel return {}; } - BAN::ErrorOr StorageDevice::write_sectors(uint64_t lba, uint64_t sector_count, BAN::ConstByteSpan buffer) + BAN::ErrorOr StorageDevice::write_sectors(uint64_t lba, size_t sector_count, BAN::ConstByteSpan buffer) { ASSERT(buffer.size() >= sector_count * sector_size()); @@ -337,4 +269,4 @@ namespace Kernel return {}; } -} \ No newline at end of file +}