diff --git a/kernel/include/kernel/FS/Inode.h b/kernel/include/kernel/FS/Inode.h index 47fb991308..6e5bb0af85 100644 --- a/kernel/include/kernel/FS/Inode.h +++ b/kernel/include/kernel/FS/Inode.h @@ -34,13 +34,17 @@ namespace Kernel IFREG = 0x8000, IFLNK = 0xA000, IFSOCK = 0xC000, + TYPE_MASK = 0xF000, }; public: virtual ~Inode() {} - bool ifdir() const { return mode() & Mode::IFDIR; } - bool ifreg() const { return mode() & Mode::IFREG; } + bool ifdir() const { return (mode() & Mode::TYPE_MASK) == Mode::IFDIR; } + bool ifblk() const { return (mode() & Mode::TYPE_MASK) == Mode::IFBLK; } + bool ifreg() const { return (mode() & Mode::TYPE_MASK) == Mode::IFREG; } + bool iflnk() const { return (mode() & Mode::TYPE_MASK) == Mode::IFLNK; } + bool ifsock() const { return (mode() & Mode::TYPE_MASK) == Mode::IFSOCK; } bool operator==(const Inode& other) const { return dev() == other.dev() && rdev() == other.rdev() && ino() == other.ino(); } diff --git a/kernel/include/kernel/FS/VirtualFileSystem.h b/kernel/include/kernel/FS/VirtualFileSystem.h index 929f85f2a8..da11cbf49f 100644 --- a/kernel/include/kernel/FS/VirtualFileSystem.h +++ b/kernel/include/kernel/FS/VirtualFileSystem.h @@ -16,7 +16,7 @@ namespace Kernel static VirtualFileSystem& get(); virtual ~VirtualFileSystem() {}; - virtual BAN::RefPtr root_inode() override { return m_root_inode; } + virtual BAN::RefPtr root_inode() override { return m_root_fs->root_inode(); } BAN::ErrorOr mount(FileSystem*, BAN::StringView); @@ -36,10 +36,9 @@ namespace Kernel private: VirtualFileSystem() = default; - BAN::ErrorOr initialize_impl(); private: - BAN::RefPtr m_root_inode; + FileSystem* m_root_fs = nullptr; BAN::Vector m_mount_points; BAN::Vector m_storage_controllers; }; diff --git a/kernel/include/kernel/Storage/ATAController.h b/kernel/include/kernel/Storage/ATAController.h index b593db71fb..8ac6af7593 100644 --- a/kernel/include/kernel/Storage/ATAController.h +++ b/kernel/include/kernel/Storage/ATAController.h @@ -1,6 +1,6 @@ #pragma once -#include +#include #include namespace Kernel @@ -38,6 +38,24 @@ namespace Kernel ATAController* controller; friend class ATAController; + + char device_name[4] {}; + + public: + virtual ino_t ino() const override { return !!slave_bit; } + virtual mode_t mode() const override { return Mode::IFBLK; } + virtual nlink_t nlink() const override { return 1; } + 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 blksize_t blksize() const override { return sector_size(); } + virtual blkcnt_t blocks() const override { return 0; } + virtual dev_t dev() const override; + virtual dev_t rdev() const override { return 0x5429; } + + virtual BAN::StringView name() const override { return BAN::StringView(device_name, sizeof(device_name) - 1); } + + virtual BAN::ErrorOr read(size_t, void*, size_t) override; }; struct ATABus @@ -54,7 +72,7 @@ namespace Kernel BAN::Error error(); }; - class ATAController : public StorageController + class ATAController final : public StorageController { public: static BAN::ErrorOr create(const PCIDevice&); @@ -71,6 +89,22 @@ namespace Kernel const PCIDevice& m_pci_device; friend class ATADevice; + + public: + virtual ino_t ino() const override { return 0; } + virtual mode_t mode() const override { return Mode::IFCHR; } + virtual nlink_t nlink() const override { return 1; } + 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 blksize_t blksize() const override { return 0; } + virtual blkcnt_t blocks() const override { return 0; } + virtual dev_t dev() const override { return DeviceManager::get().dev(); } + virtual dev_t rdev() const override { return 0x8594; } + + virtual BAN::StringView name() const override { return "hd"sv; } + + virtual BAN::ErrorOr read(size_t, void*, size_t) { return BAN::Error::from_errno(ENOTSUP); } }; } \ No newline at end of file diff --git a/kernel/include/kernel/Storage/StorageController.h b/kernel/include/kernel/Storage/StorageController.h index 0f9309b319..321c4f9188 100644 --- a/kernel/include/kernel/Storage/StorageController.h +++ b/kernel/include/kernel/Storage/StorageController.h @@ -1,18 +1,24 @@ #pragma once -#include #include namespace Kernel { - class StorageController + class StorageController : public CharacterDevice { public: BAN::Vector& devices() { return m_devices; } const BAN::Vector& devices() const { return m_devices; } protected: + void add_device(StorageDevice* device) + { + ASSERT(device); + MUST(m_devices.push_back(device)); + } + + private: BAN::Vector m_devices; }; diff --git a/kernel/include/kernel/Storage/StorageDevice.h b/kernel/include/kernel/Storage/StorageDevice.h index 2cd0bd0353..6290e3335d 100644 --- a/kernel/include/kernel/Storage/StorageDevice.h +++ b/kernel/include/kernel/Storage/StorageDevice.h @@ -16,10 +16,10 @@ namespace Kernel class StorageDevice; - class Partition + class Partition final : public BlockDevice { public: - Partition(StorageDevice&, const GUID&, const GUID&, uint64_t, uint64_t, uint64_t, const char*); + Partition(StorageDevice&, const GUID&, const GUID&, uint64_t, uint64_t, uint64_t, const char*, uint32_t); const GUID& partition_type() const { return m_type; } const GUID& partition_guid() const { return m_guid; } @@ -31,7 +31,6 @@ namespace Kernel BAN::ErrorOr read_sectors(uint64_t lba, uint8_t sector_count, uint8_t* buffer); BAN::ErrorOr write_sectors(uint64_t lba, uint8_t sector_count, const uint8_t* buffer); - bool is_used() const { uint8_t zero[16] {}; return memcmp(&m_type, zero, 16); } private: StorageDevice& m_device; @@ -41,9 +40,29 @@ namespace Kernel const uint64_t m_lba_end; const uint64_t m_attributes; char m_label[36 * 4 + 1]; + + public: + virtual ino_t ino() const override { return m_index; } + virtual mode_t mode() const override { return Mode::IFBLK | Mode::IRUSR | Mode::IRGRP; } + virtual nlink_t nlink() const override { return 1; } + 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 blksize_t blksize() const; + virtual blkcnt_t blocks() const override { return 0; } + virtual dev_t dev() const override; + virtual dev_t rdev() const { return 0x7459; } + + virtual BAN::StringView name() const override { return m_device_name; } + + virtual BAN::ErrorOr read(size_t, void*, size_t) override; + + private: + const uint32_t m_index; + BAN::String m_device_name; }; - class StorageDevice + class StorageDevice : public BlockDevice { public: virtual ~StorageDevice() {} @@ -55,10 +74,11 @@ namespace Kernel virtual uint32_t sector_size() const = 0; virtual uint64_t total_size() const = 0; - BAN::Vector& partitions() { return m_partitions; } + BAN::Vector& partitions() { return m_partitions; } + const BAN::Vector& partitions() const { return m_partitions; } private: - BAN::Vector m_partitions; + BAN::Vector m_partitions; }; } \ No newline at end of file diff --git a/kernel/kernel/Device.cpp b/kernel/kernel/Device.cpp index fdfe0feb07..3520ef6bcb 100644 --- a/kernel/kernel/Device.cpp +++ b/kernel/kernel/Device.cpp @@ -1,12 +1,20 @@ +#include #include #include +#include #include +#include +#include namespace Kernel { static DeviceManager* s_instance = nullptr; + Device::Device() + : m_create_time({ BAN::to_unix_time(RTC::get_current_time()), 0 }) + { } + void DeviceManager::initialize() { ASSERT(s_instance == nullptr); @@ -14,6 +22,43 @@ namespace Kernel s_instance = new DeviceManager; ASSERT(s_instance != nullptr); + for (const auto& pci_device : PCI::get().devices()) + { + switch (pci_device.class_code()) + { + case 0x01: + { + StorageController* controller = nullptr; + switch (pci_device.subclass()) + { + case 0x01: + if (auto res = ATAController::create(pci_device); res.is_error()) + dprintln("{}", res.error()); + else + controller = res.value(); + break; + default: + dprintln("unsupported storage device (pci subclass {2H})", pci_device.subclass()); + break; + } + + if (controller) + { + s_instance->add_device(controller); + for (auto* device : controller->devices()) + { + s_instance->add_device(device); + for (auto* partition : device->partitions()) + s_instance->add_device(partition); + } + } + break; + } + default: + break; + } + } + MUST(Process::create_kernel( [](void*) { diff --git a/kernel/kernel/FS/VirtualFileSystem.cpp b/kernel/kernel/FS/VirtualFileSystem.cpp index 39d2c39f22..046f7077cb 100644 --- a/kernel/kernel/FS/VirtualFileSystem.cpp +++ b/kernel/kernel/FS/VirtualFileSystem.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -17,13 +18,13 @@ namespace Kernel s_instance = new VirtualFileSystem(); if (s_instance == nullptr) return BAN::Error::from_errno(ENOMEM); + BAN::ScopeGuard guard([] { delete s_instance; s_instance = nullptr; } ); - if (auto res = s_instance->initialize_impl(); res.is_error()) - { - delete s_instance; - s_instance = nullptr; - return res; - } + auto partition_inode = TRY(DeviceManager::get().read_directory_inode("hda1")); + s_instance->m_root_fs = TRY(Ext2FS::create(*(Partition*)partition_inode.ptr())); + TRY(s_instance->mount(&DeviceManager::get(), "/dev")); + + guard.disable(); return {}; } @@ -34,91 +35,6 @@ namespace Kernel return *s_instance; } - BAN::ErrorOr VirtualFileSystem::initialize_impl() - { - // Initialize all storage controllers - for (auto& device : PCI::get().devices()) - { - if (device.class_code() != 0x01) - continue; - - switch (device.subclass()) - { - case 0x0: - dwarnln("unsupported SCSI Bus Controller"); - break; - case 0x1: - case 0x5: - TRY(m_storage_controllers.push_back(TRY(ATAController::create(device)))); - break; - case 0x2: - dwarnln("unsupported Floppy Disk Controller"); - break; - case 0x3: - dwarnln("unsupported IPI Bus Controller"); - break; - case 0x4: - dwarnln("unsupported RAID Controller"); - break; - case 0x6: - dwarnln("unsupported Serial ATA Controller"); - break; - case 0x7: - dwarnln("unsupported Serial Attached SCSI Controller"); - break; - case 0x8: - dwarnln("unsupported Non-Volatile Memory Controller"); - break; - case 0x80: - dwarnln("unsupported Unknown Storage Controller"); - break; - } - } - - // Initialize partitions on all devices on found controllers - for (auto controller : m_storage_controllers) - { - for (auto device : controller->devices()) - { - if (device->total_size() == 0) - continue; - - auto result = device->initialize_partitions(); - if (result.is_error()) - { - dwarnln("{}", result.error()); - continue; - } - - for (auto& partition : device->partitions()) - { - if (partition.label() == "banan-root"sv) - { - if (root_inode()) - dwarnln("multiple root partitions found"); - else - { - auto ext2fs_or_error = Ext2FS::create(partition); - if (ext2fs_or_error.is_error()) - dwarnln("{}", ext2fs_or_error.error()); - else - // FIXME: We leave a dangling pointer to ext2fs. This might be okay since - // root fs sould probably be always mounted - m_root_inode = ext2fs_or_error.value()->root_inode(); - } - } - } - } - } - - if (!root_inode()) - derrorln("Could not locate root partition"); - - TRY(mount(&DeviceManager::get(), "/dev")); - - return {}; - } - BAN::ErrorOr VirtualFileSystem::mount(FileSystem* file_system, BAN::StringView path) { auto file = TRY(file_from_absolute_path(path)); diff --git a/kernel/kernel/Storage/ATAController.cpp b/kernel/kernel/Storage/ATAController.cpp index 0f750e07f8..230360d03d 100644 --- a/kernel/kernel/Storage/ATAController.cpp +++ b/kernel/kernel/Storage/ATAController.cpp @@ -94,6 +94,11 @@ namespace Kernel device.bus = &bus; device.controller = this; + device.device_name[0] = 'h'; + device.device_name[1] = 'd'; + device.device_name[2] = 'a' + bus_index * 2 + device_index; + device.device_name[3] = '\0'; + bus.write(ATA_PORT_DRIVE_SELECT, 0xA0 | device.slave_bit); PIT::sleep(1); @@ -162,7 +167,15 @@ namespace Kernel } device.model[40] = 0; - TRY(m_devices.push_back(&device)); + if (auto res = device.initialize_partitions(); res.is_error()) + { + dprintln("could not initialize partitions on device {}", device.device_name); + device.type = ATADevice::DeviceType::Unknown; + } + else + { + add_device(&device); + } } } @@ -342,4 +355,18 @@ namespace Kernel ASSERT_NOT_REACHED(); } + dev_t ATADevice::dev() const + { + ASSERT(controller); + return controller->dev(); + } + + BAN::ErrorOr ATADevice::read(size_t offset, void* buffer, size_t bytes) + { + if (offset % sector_size() || bytes % sector_size()) + return BAN::Error::from_errno(EINVAL); + TRY(read_sectors(offset / sector_size(), bytes / sector_size(), (uint8_t*)buffer)); + return bytes; + } + } \ No newline at end of file diff --git a/kernel/kernel/Storage/StorageDevice.cpp b/kernel/kernel/Storage/StorageDevice.cpp index 222f30d401..fd73a1296e 100644 --- a/kernel/kernel/Storage/StorageDevice.cpp +++ b/kernel/kernel/Storage/StorageDevice.cpp @@ -168,32 +168,41 @@ 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) + continue; + char utf8_name[36 * 4 + 1]; BAN::UTF8::from_codepoints(entry.partition_name, 36, utf8_name); - MUST(m_partitions.emplace_back( + Partition* partition = new Partition( *this, entry.partition_type_guid, entry.unique_partition_guid, entry.starting_lba, entry.ending_lba, entry.attributes, - utf8_name - )); + utf8_name, + i + ); + ASSERT(partition != nullptr); + MUST(m_partitions.push_back(partition)); } return {}; } - Partition::Partition(StorageDevice& device, const GUID& type, const GUID& guid, uint64_t start, uint64_t end, uint64_t attr, const char* label) + 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) : m_device(device) , m_type(type) , m_guid(guid) , m_lba_start(start) , m_lba_end(end) , m_attributes(attr) + , m_index(index) + , m_device_name(BAN::String::formatted("{}{}", m_device.name(), index)) { - memcpy(m_label, label, sizeof(m_label)); + memcpy(m_label, label, sizeof(m_label)); } BAN::ErrorOr Partition::read_sectors(uint64_t lba, uint8_t sector_count, uint8_t* buffer) @@ -214,4 +223,22 @@ namespace Kernel return {}; } + blksize_t Partition::blksize() const + { + return m_device.blksize(); + } + + dev_t Partition::dev() const + { + return m_device.dev(); + } + + BAN::ErrorOr Partition::read(size_t offset, void* buffer, size_t bytes) + { + if (offset % m_device.sector_size() || bytes % m_device.sector_size()) + return BAN::Error::from_errno(ENOTSUP); + TRY(read_sectors(offset / m_device.sector_size(), bytes / m_device.sector_size(), (uint8_t*)buffer)); + return bytes; + } + } \ No newline at end of file