Kernel: Rewrite whole device structure

We now have DevFileSystem which is derived from RamFileSystem. All
devices are RamInodes. We don't have separate DeviceManager anymore.
To iterate over devices, you can loop througn every inode in devfs.
This commit is contained in:
Bananymous 2023-07-10 23:17:14 +03:00
parent f88b9ae4f2
commit 9bcfb34524
34 changed files with 334 additions and 408 deletions

View File

@ -15,9 +15,9 @@ set(KERNEL_SOURCES
kernel/CPUID.cpp
kernel/Debug.cpp
kernel/Device.cpp
kernel/DeviceManager.cpp
kernel/Errors.cpp
kernel/Font.cpp
kernel/FS/DevFS/FileSystem.cpp
kernel/FS/Ext2.cpp
kernel/FS/Inode.cpp
kernel/FS/Pipe.cpp

View File

@ -1,53 +1,41 @@
#pragma once
#include <kernel/DeviceManager.h>
#include <kernel/FS/RamFS/Inode.h>
namespace Kernel
{
class Device : public Inode
class Device : public RamInode
{
public:
Device();
virtual ~Device() {}
Device(mode_t, uid_t, gid_t);
virtual ~Device() = default;
virtual void update() {}
virtual bool is_device() const override { return true; }
virtual bool is_partition() const { return false; }
virtual ino_t ino() const override { return m_ino_t; }
virtual nlink_t nlink() const override { return 1; }
virtual off_t size() const override { return 0; }
virtual timespec atime() const override { return m_create_time; }
virtual timespec mtime() const override { return m_create_time; }
virtual timespec ctime() const override { return m_create_time; }
virtual blksize_t blksize() const override { return DeviceManager::get().blksize(); }
virtual blkcnt_t blocks() const override { return DeviceManager::get().blocks(); }
virtual dev_t dev() const override { return DeviceManager::get().dev(); }
/*
a device has to overload
virtual Mode mode() const;
virtual uid_t uid() const;
virtual gid_t gid() const;
virtual dev_t rdev() const;
virtual BAN::StringView name() const;
*/
private:
const timespec m_create_time;
const ino_t m_ino_t;
virtual dev_t rdev() const override = 0;
};
class BlockDevice : public Device
{
public:
BlockDevice(mode_t mode, uid_t uid, gid_t gid)
: Device(Mode::IFBLK | mode, uid, gid)
{
ASSERT(Device::mode().ifblk());
}
};
class CharacterDevice : public Device
{
public:
CharacterDevice(mode_t mode, uid_t uid, gid_t gid)
: Device(Mode::IFCHR | mode, uid, gid)
{
ASSERT(Device::mode().ifchr());
}
};
}

View File

@ -1,72 +0,0 @@
#pragma once
#include <BAN/StringView.h>
#include <kernel/FS/FileSystem.h>
#include <kernel/SpinLock.h>
#include <sys/sysmacros.h>
namespace Kernel
{
class Device;
class DeviceManager final : public FileSystem, public Inode
{
BAN_NON_COPYABLE(DeviceManager);
BAN_NON_MOVABLE(DeviceManager);
public:
static DeviceManager& get();
void initialize_pci_devices();
void initialize_updater();
ino_t get_next_ino() const;
dev_t get_next_rdev() const;
uint8_t get_next_input_dev() const;
void update();
void add_device(Device*);
virtual BAN::RefPtr<Inode> root_inode() override { return this; }
virtual BAN::StringView name() const override { return "device-manager"; }
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> directory_find_inode(BAN::StringView) override;
virtual BAN::ErrorOr<void> directory_read_next_entries(off_t, DirectoryEntryList*, size_t) override;
private:
DeviceManager() = default;
private:
SpinLock m_lock;
BAN::Vector<Device*> m_devices;
friend class BAN::RefPtr<DeviceManager>;
public:
virtual ino_t ino() const override { return 0; }
virtual Mode mode() const override { return { Mode::IFDIR | Mode::IRUSR | Mode::IWUSR | Mode::IXUSR | Mode::IRGRP | Mode::IXGRP | Mode::IROTH | Mode::IXOTH }; }
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 timespec atime() const override { return { 0, 0 }; }
virtual timespec mtime() const override { return { 0, 0 }; }
virtual timespec ctime() const override { return { 0, 0 }; }
virtual blksize_t blksize() const override { ASSERT(m_blksize); return m_blksize; }
virtual blkcnt_t blocks() const override { return 0; }
virtual dev_t dev() const override { return makedev(0, 5); }
virtual dev_t rdev() const override { return 0; }
virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t) { return BAN::Error::from_errno(EISDIR); }
virtual BAN::ErrorOr<void> create_file(BAN::StringView, mode_t) { return BAN::Error::from_errno(ENOTSUP); }
void set_blksize(blksize_t blksize) { m_blksize = blksize; }
private:
blksize_t m_blksize = 0;
};
}

View File

@ -0,0 +1,30 @@
#pragma once
#include <kernel/Device.h>
#include <kernel/FS/RamFS/FileSystem.h>
namespace Kernel
{
class DevFileSystem final : public RamFileSystem
{
public:
static void initialize();
static DevFileSystem& get();
void initialize_device_updater();
void add_device(BAN::StringView path, BAN::RefPtr<Device>);
dev_t get_next_rdev();
private:
DevFileSystem(size_t size)
: RamFileSystem(size)
{ }
private:
SpinLock m_device_lock;
};
}

View File

@ -137,8 +137,6 @@ namespace Kernel
virtual dev_t dev() const override { return 0; }
virtual dev_t rdev() const override { return 0; }
virtual BAN::StringView name() const override { return m_name; }
virtual BAN::ErrorOr<BAN::String> link_target() override;
virtual BAN::ErrorOr<void> directory_read_next_entries(off_t, DirectoryEntryList*, size_t) override;

View File

@ -78,8 +78,6 @@ namespace Kernel
virtual bool is_device() const { return false; }
virtual bool is_pipe() const { return false; }
virtual BAN::StringView name() const = 0;
virtual BAN::ErrorOr<BAN::String> link_target() { ASSERT_NOT_REACHED(); }
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> directory_find_inode(BAN::StringView) { if (!mode().ifdir()) return BAN::Error::from_errno(ENOTDIR); ASSERT_NOT_REACHED(); }

View File

@ -30,8 +30,6 @@ namespace Kernel
virtual dev_t dev() const override { return 0; } // FIXME
virtual dev_t rdev() const override { return 0; } // FIXME
virtual BAN::StringView name() const override { return ""sv; }
virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t) override;
virtual BAN::ErrorOr<size_t> write(size_t, const void*, size_t) override;

View File

@ -8,13 +8,15 @@ namespace Kernel
{
class RamInode;
class RamDirectoryInode;
class RamFileSystem final : public FileSystem
class RamFileSystem : public FileSystem
{
public:
static BAN::ErrorOr<RamFileSystem*> create(size_t size, mode_t, uid_t, gid_t);
~RamFileSystem() = default;
virtual ~RamFileSystem() = default;
BAN::ErrorOr<void> set_root_inode(BAN::RefPtr<RamDirectoryInode>);
virtual BAN::RefPtr<Inode> root_inode() override { return m_inodes[m_root_inode]; }
BAN::ErrorOr<void> add_inode(BAN::RefPtr<RamInode>);
@ -23,15 +25,19 @@ namespace Kernel
blksize_t blksize() const { return m_blksize; }
ino_t next_ino() { return m_next_ino++; }
private:
RamFileSystem() = default;
void for_each_inode(void (*callback)(BAN::RefPtr<RamInode>));
protected:
RamFileSystem(size_t size)
: m_size(size)
{ }
private:
SpinLock m_lock;
RecursiveSpinLock m_lock;
size_t m_size { 0 };
BAN::HashMap<ino_t, BAN::RefPtr<RamInode>> m_inodes;
ino_t m_root_inode;
ino_t m_root_inode { 0 };
const blksize_t m_blksize = PAGE_SIZE;
ino_t m_next_ino { 1 };

View File

@ -12,6 +12,7 @@ namespace Kernel
class RamInode : public Inode
{
public:
static BAN::ErrorOr<BAN::RefPtr<RamInode>> create(RamFileSystem&, mode_t, uid_t, gid_t);
virtual ~RamInode() = default;
virtual ino_t ino() const override { return m_inode_info.ino; }
@ -28,8 +29,6 @@ namespace Kernel
virtual dev_t dev() const override { return m_inode_info.dev; }
virtual dev_t rdev() const override { return m_inode_info.rdev; }
virtual BAN::StringView name() const override { ASSERT_NOT_REACHED(); }
virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t) override;
virtual BAN::ErrorOr<size_t> write(size_t, const void*, size_t) override;
@ -39,7 +38,6 @@ namespace Kernel
protected:
RamInode(RamFileSystem& fs, mode_t, uid_t, gid_t);
static BAN::ErrorOr<BAN::RefPtr<RamInode>> create(RamFileSystem&, mode_t, uid_t, gid_t);
protected:
struct FullInodeInfo
@ -71,15 +69,17 @@ namespace Kernel
class RamDirectoryInode final : public RamInode
{
public:
static BAN::ErrorOr<BAN::RefPtr<RamDirectoryInode>> create(RamFileSystem&, ino_t parent, mode_t, uid_t, gid_t);
~RamDirectoryInode() = default;
virtual BAN::ErrorOr<BAN::RefPtr<Inode>> directory_find_inode(BAN::StringView) override;
virtual BAN::ErrorOr<void> directory_read_next_entries(off_t, DirectoryEntryList*, size_t) override;
virtual BAN::ErrorOr<void> create_file(BAN::StringView, mode_t, uid_t, gid_t) override;
BAN::ErrorOr<void> add_inode(BAN::StringView, BAN::RefPtr<RamInode>);
private:
RamDirectoryInode(RamFileSystem&, ino_t parent, mode_t, uid_t, gid_t);
static BAN::ErrorOr<BAN::RefPtr<RamDirectoryInode>> create(RamFileSystem&, ino_t parent, mode_t, uid_t, gid_t);
private:
static constexpr size_t m_name_max = NAME_MAX;

View File

@ -12,9 +12,9 @@ namespace Kernel::Input
virtual void on_byte(uint8_t) = 0;
public:
virtual Mode mode() const override { return { Mode::IFCHR | Mode::IRUSR | Mode::IRGRP }; }
virtual uid_t uid() const override { return 0; }
virtual gid_t gid() const override { return 0; }
PS2Device()
: CharacterDevice(Mode::IRUSR | Mode::IRGRP, 0, 0)
{ }
};
class PS2Controller

View File

@ -60,13 +60,10 @@ namespace Kernel::Input
Semaphore m_semaphore;
public:
virtual BAN::StringView name() const override { return m_name; }
virtual dev_t rdev() const override { return m_rdev; }
virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t) override;
private:
const BAN::String m_name;
const dev_t m_rdev;
};

View File

@ -60,6 +60,7 @@ namespace Kernel
void check_device(uint8_t bus, uint8_t dev);
void check_bus(uint8_t bus);
void check_all_buses();
void initialize_devices();
private:
BAN::Vector<PCIDevice> m_devices;

View File

@ -20,28 +20,28 @@ namespace Kernel
};
public:
static ATABus* create(ATAController*, uint16_t base, uint16_t ctrl, uint8_t irq);
static ATABus* create(ATAController&, uint16_t base, uint16_t ctrl, uint8_t irq);
BAN::ErrorOr<void> read(ATADevice*, uint64_t, uint8_t, uint8_t*);
BAN::ErrorOr<void> write(ATADevice*, uint64_t, uint8_t, const uint8_t*);
BAN::ErrorOr<void> read(ATADevice&, uint64_t, uint8_t, uint8_t*);
BAN::ErrorOr<void> write(ATADevice&, uint64_t, uint8_t, const uint8_t*);
ATAController* controller() { return m_controller; }
ATAController& controller() { return m_controller; }
void on_irq();
private:
ATABus(ATAController* controller, uint16_t base, uint16_t ctrl)
ATABus(ATAController& controller, uint16_t base, uint16_t ctrl)
: m_controller(controller)
, m_base(base)
, m_ctrl(ctrl)
{}
void initialize(uint8_t irq);
void select_device(const ATADevice*);
DeviceType identify(const ATADevice*, uint16_t*);
void select_device(const ATADevice&);
DeviceType identify(const ATADevice&, uint16_t*);
void block_until_irq();
uint8_t device_index(const ATADevice*) const;
uint8_t device_index(const ATADevice&) const;
uint8_t io_read(uint16_t);
void io_write(uint16_t, uint8_t);
@ -51,14 +51,14 @@ namespace Kernel
BAN::Error error();
private:
ATAController* m_controller;
ATAController& m_controller;
const uint16_t m_base;
const uint16_t m_ctrl;
SpinLock m_lock;
bool m_has_got_irq { false };
ATADevice* m_devices[2] { nullptr, nullptr };
BAN::RefPtr<ATADevice> m_devices[2] {};
friend class ATAController;
};

View File

@ -1,6 +1,5 @@
#pragma once
#include <kernel/DeviceManager.h>
#include <kernel/PCI.h>
#include <kernel/SpinLock.h>
#include <kernel/Storage/StorageController.h>
@ -13,16 +12,12 @@ namespace Kernel
class ATAController final : public StorageController
{
public:
static BAN::ErrorOr<ATAController*> create(const PCIDevice&);
static BAN::ErrorOr<BAN::RefPtr<ATAController>> create(const PCIDevice&);
virtual BAN::Vector<StorageDevice*> devices() override;
uint8_t next_device_index() const;
virtual BAN::Vector<BAN::RefPtr<StorageDevice>> devices() override;
private:
ATAController()
: m_rdev(makedev(DeviceManager::get().get_next_rdev(), 0))
{ }
ATAController();
BAN::ErrorOr<void> initialize(const PCIDevice& device);
private:
@ -35,8 +30,6 @@ namespace Kernel
virtual gid_t gid() const override { return 0; }
virtual dev_t rdev() const override { return m_rdev; }
virtual BAN::StringView name() const override { return "hd"sv; }
virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t) { return BAN::Error::from_errno(ENOTSUP); }
private:

View File

@ -9,10 +9,7 @@ namespace Kernel
class ATADevice final : public StorageDevice
{
public:
ATADevice(ATABus* bus)
: m_bus(bus)
, m_rdev(makedev(DeviceManager::get().get_next_rdev(), 0))
{ }
ATADevice(ATABus&);
BAN::ErrorOr<void> initialize(ATABus::DeviceType, const uint16_t*);
virtual uint32_t sector_size() const override { return m_sector_words * 2; }
@ -25,7 +22,7 @@ namespace Kernel
virtual BAN::ErrorOr<void> write_sectors_impl(uint64_t, uint8_t, const uint8_t*) override;
private:
ATABus* m_bus;
ATABus& m_bus;
uint8_t m_index;
ATABus::DeviceType m_type;
@ -44,13 +41,10 @@ namespace Kernel
virtual gid_t gid() const override { return 0; }
virtual dev_t rdev() const override { return m_rdev; }
virtual BAN::StringView name() const override { return BAN::StringView(m_device_name, sizeof(m_device_name) - 1); }
virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t) override;
public:
const dev_t m_rdev;
char m_device_name[4] {};
};
}

View File

@ -8,7 +8,10 @@ namespace Kernel
class StorageController : public CharacterDevice
{
public:
virtual BAN::Vector<StorageDevice*> devices() = 0;
StorageController()
: CharacterDevice(0660, 0, 0)
{ }
virtual BAN::Vector<BAN::RefPtr<StorageDevice>> devices() = 0;
};
}

View File

@ -48,20 +48,20 @@ namespace Kernel
virtual Mode mode() const override { return { Mode::IFBLK | Mode::IRUSR | Mode::IRGRP }; }
virtual uid_t uid() const override { return 0; }
virtual gid_t gid() const override { return 0; }
virtual dev_t rdev() const override;
virtual BAN::StringView name() const override { return m_device_name; }
virtual dev_t rdev() const override { return m_rdev; }
virtual BAN::ErrorOr<size_t> read(size_t, void*, size_t) override;
private:
const uint32_t m_index;
BAN::String m_device_name;
const dev_t m_rdev;
};
class StorageDevice : public BlockDevice
{
public:
StorageDevice()
: BlockDevice(0660, 0, 0)
{ }
virtual ~StorageDevice();
BAN::ErrorOr<void> initialize_partitions();
@ -74,7 +74,7 @@ namespace Kernel
BAN::Vector<Partition*>& partitions() { return m_partitions; }
const BAN::Vector<Partition*>& partitions() const { return m_partitions; }
protected:
virtual BAN::ErrorOr<void> read_sectors_impl(uint64_t lba, uint8_t sector_count, uint8_t* buffer) = 0;
virtual BAN::ErrorOr<void> write_sectors_impl(uint64_t lba, uint8_t sector_count, const uint8_t* buffer) = 0;

View File

@ -113,11 +113,9 @@ namespace Kernel
virtual uid_t uid() const override { return 0; }
virtual gid_t gid() const override { return 0; }
virtual dev_t rdev() const override { return m_rdev; }
virtual BAN::StringView name() const { return m_name; }
private:
dev_t m_rdev;
BAN::String m_name;
};
}

View File

@ -1,13 +1,11 @@
#include <BAN/Time.h>
#include <kernel/Device.h>
#include <kernel/RTC.h>
#include <kernel/FS/DevFS/FileSystem.h>
namespace Kernel
{
Device::Device()
: m_create_time({ BAN::to_unix_time(RTC::get_current_time()), 0 })
, m_ino_t(DeviceManager::get().get_next_ino())
Device::Device(mode_t mode, uid_t uid, gid_t gid)
: RamInode(DevFileSystem::get(), mode, uid, gid)
{ }
}

View File

@ -1,163 +0,0 @@
#include <kernel/DeviceManager.h>
#include <kernel/LockGuard.h>
#include <kernel/PCI.h>
#include <kernel/Process.h>
#include <kernel/Storage/ATAController.h>
namespace Kernel
{
DeviceManager& DeviceManager::get()
{
static DeviceManager instance;
return instance;
}
void DeviceManager::initialize_pci_devices()
{
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 {2H}.{2H}.{2H})", pci_device.class_code(), pci_device.subclass(), pci_device.prog_if());
break;
}
if (controller)
{
add_device(controller);
for (auto* device : controller->devices())
{
add_device(device);
if (auto res = device->initialize_partitions(); res.is_error())
dprintln("{}", res.error());
else
{
for (auto* partition : device->partitions())
add_device(partition);
}
}
}
break;
}
default:
break;
}
}
}
void DeviceManager::initialize_updater()
{
Process::create_kernel(
[](void*)
{
while (true)
{
DeviceManager::get().update();
PIT::sleep(1);
}
}, nullptr
);
}
ino_t DeviceManager::get_next_ino() const
{
static ino_t next_ino = 1;
return next_ino++;
}
dev_t DeviceManager::get_next_rdev() const
{
static dev_t next_dev = 1;
return next_dev++;
}
uint8_t DeviceManager::get_next_input_dev() const
{
static uint8_t next_dev = 0;
return next_dev++;
}
void DeviceManager::update()
{
LockGuard _(m_lock);
for (Device* device : m_devices)
device->update();
}
void DeviceManager::add_device(Device* device)
{
LockGuard _(m_lock);
MUST(m_devices.push_back(device));
}
BAN::ErrorOr<BAN::RefPtr<Inode>> DeviceManager::directory_find_inode(BAN::StringView name)
{
LockGuard _(m_lock);
if (name == "."sv || name == ".."sv)
return BAN::RefPtr<Inode>(this);
for (Device* device : m_devices)
if (device->name() == name)
return BAN::RefPtr<Inode>(device);
return BAN::Error::from_errno(ENOENT);
}
BAN::ErrorOr<void> DeviceManager::directory_read_next_entries(off_t offset, DirectoryEntryList* list, size_t list_size)
{
if (offset != 0)
{
list->entry_count = 0;
return {};
}
LockGuard _(m_lock);
size_t needed_size = sizeof(DirectoryEntryList);
needed_size += sizeof(DirectoryEntry) + 2;
needed_size += sizeof(DirectoryEntry) + 3;
for (Device* device : m_devices)
needed_size += sizeof(DirectoryEntry) + device->name().size() + 1;
if (needed_size > list_size)
return BAN::Error::from_errno(EINVAL);
DirectoryEntry* ptr = list->array;
ptr->dirent.d_ino = ino();
ptr->rec_len = sizeof(DirectoryEntry) + 2;
memcpy(ptr->dirent.d_name, ".", 2);
ptr = ptr->next();
ptr->dirent.d_ino = 69; // FIXME: store parent inode number when we implement proper RAM fs
ptr->rec_len = sizeof(DirectoryEntry) + 3;
memcpy(ptr->dirent.d_name, "..", 3);
ptr = ptr->next();
for (Device* device : m_devices)
{
ptr->dirent.d_ino = device->ino();
ptr->rec_len = sizeof(DirectoryEntry) + device->name().size() + 1;
memcpy(ptr->dirent.d_name, device->name().data(), device->name().size());
ptr->dirent.d_name[device->name().size()] = '\0';
ptr = ptr->next();
}
list->entry_count = m_devices.size() + 2;
return {};
}
}

View File

@ -0,0 +1,63 @@
#include <BAN/ScopeGuard.h>
#include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/FS/RamFS/Inode.h>
#include <kernel/LockGuard.h>
#include <kernel/Process.h>
namespace Kernel
{
static DevFileSystem* s_instance = nullptr;
void DevFileSystem::initialize()
{
ASSERT(s_instance == nullptr);
s_instance = new DevFileSystem(1024 * 1024);
ASSERT(s_instance);
auto root_inode = MUST(RamDirectoryInode::create(*s_instance, 0, Inode::Mode::IFDIR | 0755, 0, 0));
MUST(s_instance->set_root_inode(root_inode));
}
DevFileSystem& DevFileSystem::get()
{
ASSERT(s_instance);
return *s_instance;
}
void DevFileSystem::initialize_device_updater()
{
Process::create_kernel(
[](void*)
{
while (true)
{
s_instance->m_device_lock.lock();
s_instance->for_each_inode(
[](BAN::RefPtr<RamInode> inode)
{
if (inode->is_device())
((Device*)inode.ptr())->update();
}
);
s_instance->m_device_lock.unlock();
PIT::sleep(1);
}
}, nullptr
);
}
void DevFileSystem::add_device(BAN::StringView path, BAN::RefPtr<Device> device)
{
ASSERT(!path.contains('/'));
MUST(reinterpret_cast<RamDirectoryInode*>(root_inode().ptr())->add_inode(path, device));
}
dev_t DevFileSystem::get_next_rdev()
{
static dev_t next_rdev = 1;
return next_rdev++;
}
}

View File

@ -9,22 +9,29 @@ namespace Kernel
BAN::ErrorOr<RamFileSystem*> RamFileSystem::create(size_t size, mode_t mode, uid_t uid, gid_t gid)
{
auto* ramfs = new RamFileSystem;
auto* ramfs = new RamFileSystem(size);
if (ramfs == nullptr)
return BAN::Error::from_errno(ENOMEM);
ramfs->m_size = size;
BAN::ScopeGuard deleter([ramfs] { delete ramfs; });
auto root_inode = TRY(RamDirectoryInode::create(*ramfs, 0, mode, uid, gid));
TRY(ramfs->add_inode(root_inode));
ramfs->m_root_inode = root_inode->ino();
TRY(ramfs->set_root_inode(root_inode));;
deleter.disable();
return ramfs;
}
BAN::ErrorOr<void> RamFileSystem::set_root_inode(BAN::RefPtr<RamDirectoryInode> root_inode)
{
LockGuard _(m_lock);
ASSERT(m_root_inode == 0);
TRY(add_inode(root_inode));
m_root_inode = root_inode->ino();
return {};
}
BAN::ErrorOr<void> RamFileSystem::add_inode(BAN::RefPtr<RamInode> inode)
{
LockGuard _(m_lock);
@ -42,4 +49,11 @@ namespace Kernel
return m_inodes[ino];
}
void RamFileSystem::for_each_inode(void (*callback)(BAN::RefPtr<RamInode>))
{
LockGuard _(m_lock);
for (auto& [_, inode] : m_inodes)
callback(inode);
}
}

View File

@ -180,13 +180,6 @@ namespace Kernel
BAN::ErrorOr<void> RamDirectoryInode::create_file(BAN::StringView name, mode_t mode, uid_t uid, gid_t gid)
{
if (name.size() > m_name_max)
return BAN::Error::from_errno(ENAMETOOLONG);
for (auto& entry : m_entries)
if (name == entry.name)
return BAN::Error::from_errno(EEXIST);
BAN::RefPtr<RamInode> inode;
if (Mode{ mode }.ifreg())
inode = TRY(RamInode::create(m_fs, mode, uid, gid));
@ -195,6 +188,20 @@ namespace Kernel
else
ASSERT_NOT_REACHED();
TRY(add_inode(name, inode));
return {};
}
BAN::ErrorOr<void> RamDirectoryInode::add_inode(BAN::StringView name, BAN::RefPtr<RamInode> inode)
{
if (name.size() > m_name_max)
return BAN::Error::from_errno(ENAMETOOLONG);
for (auto& entry : m_entries)
if (name == entry.name)
return BAN::Error::from_errno(EEXIST);
TRY(m_entries.push_back({ }));
Entry& entry = m_entries.back();
strcpy(entry.name, name.data());

View File

@ -1,6 +1,6 @@
#include <BAN/ScopeGuard.h>
#include <BAN/StringView.h>
#include <kernel/DeviceManager.h>
#include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/FS/Ext2.h>
#include <kernel/FS/RamFS/FileSystem.h>
#include <kernel/FS/RamFS/Inode.h>
@ -22,13 +22,11 @@ namespace Kernel
ASSERT(root.size() >= 5 && root.substring(0, 5) == "/dev/"sv);;
root = root.substring(5);
auto partition_inode = MUST(DeviceManager::get().directory_find_inode(root));
auto partition_inode = MUST(DevFileSystem::get().root_inode()->directory_find_inode(root));
s_instance->m_root_fs = MUST(Ext2FS::create(*(Partition*)partition_inode.ptr()));
Credentials root_creds { 0, 0, 0, 0 };
DeviceManager::get().set_blksize(s_instance->m_root_fs->root_inode()->blksize());
MUST(s_instance->mount(root_creds, &DeviceManager::get(), "/dev"));
MUST(s_instance->mount(root_creds, &DevFileSystem::get(), "/dev"));
mode_t tmpfs_mode = Inode::Mode::IFDIR
| Inode::Mode::IRUSR | Inode::Mode::IWUSR | Inode::Mode::IXUSR

View File

@ -1,6 +1,6 @@
#include <BAN/ScopeGuard.h>
#include <kernel/ACPI.h>
#include <kernel/DeviceManager.h>
#include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/IDT.h>
#include <kernel/Input/PS2Controller.h>
#include <kernel/Input/PS2Keyboard.h>
@ -258,14 +258,14 @@ namespace Kernel::Input
IDT::register_irq_handler(PS2::IRQ::DEVICE0, device0_irq);
InterruptController::get().enable_irq(PS2::IRQ::DEVICE0);
config |= PS2::Config::INTERRUPT_FIRST_PORT;
DeviceManager::get().add_device(m_devices[0]);
DevFileSystem::get().add_device("input0", m_devices[0]);
}
if (m_devices[1])
{
IDT::register_irq_handler(PS2::IRQ::DEVICE1, device1_irq);
InterruptController::get().enable_irq(PS2::IRQ::DEVICE1);
config |= PS2::Config::INTERRUPT_SECOND_PORT;
DeviceManager::get().add_device(m_devices[1]);
DevFileSystem::get().add_device("input1", m_devices[1]);
}
controller_send_command(PS2::Command::WRITE_CONFIG, config);

View File

@ -1,7 +1,10 @@
#include <BAN/ScopeGuard.h>
#include <kernel/CriticalScope.h>
#include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/Input/PS2Keyboard.h>
#include <sys/sysmacros.h>
#define SET_MASK(byte, mask, on_off) ((on_off) ? ((byte) | (mask)) : ((byte) & ~(mask)))
#define TOGGLE_MASK(byte, mask) ((byte) ^ (mask))
@ -50,8 +53,7 @@ namespace Kernel::Input
PS2Keyboard::PS2Keyboard(PS2Controller& controller)
: m_controller(controller)
, m_name(BAN::String::formatted("input{}", DeviceManager::get().get_next_input_dev()))
, m_rdev(makedev(DeviceManager::get().get_next_rdev(), 0))
, m_rdev(makedev(DevFileSystem::get().get_next_rdev(), 0))
{ }
void PS2Keyboard::on_byte(uint8_t byte)

View File

@ -1,5 +1,6 @@
#include <kernel/IO.h>
#include <kernel/PCI.h>
#include <kernel/Storage/ATAController.h>
#define INVALID 0xFFFF
#define MULTI_FUNCTION 0x80
@ -18,6 +19,7 @@ namespace Kernel
s_instance = new PCI();
ASSERT(s_instance);
s_instance->check_all_buses();
s_instance->initialize_devices();
}
PCI& PCI::get()
@ -91,6 +93,32 @@ namespace Kernel
}
}
void PCI::initialize_devices()
{
for (const auto& pci_device : PCI::get().devices())
{
switch (pci_device.class_code())
{
case 0x01:
{
switch (pci_device.subclass())
{
case 0x01:
if (auto res = ATAController::create(pci_device); res.is_error())
dprintln("{}", res.error());
break;
default:
dprintln("unsupported storage device (pci {2H}.{2H}.{2H})", pci_device.class_code(), pci_device.subclass(), pci_device.prog_if());
break;
}
break;
}
default:
break;
}
}
}
PCIDevice::PCIDevice(uint8_t bus, uint8_t dev, uint8_t func)
: m_bus(bus), m_dev(dev), m_func(func)
{

View File

@ -11,6 +11,7 @@
#include <fcntl.h>
#include <stdio.h>
#include <sys/sysmacros.h>
namespace Kernel
{
@ -749,8 +750,9 @@ namespace Kernel
LockGuard _(m_lock);
if (m_tty == nullptr)
buffer[0] = '\0';
strcpy(buffer, "/dev/");
strcpy(buffer + 5, m_tty->name().data());
ASSERT(minor(m_tty->rdev()) < 10);
strcpy(buffer, "/dev/tty1");
buffer[8] += minor(m_tty->rdev());
return 0;
}

View File

@ -44,7 +44,7 @@ namespace Kernel
ASSERT_NOT_REACHED();
}
ATABus* ATABus::create(ATAController* controller, uint16_t base, uint16_t ctrl, uint8_t irq)
ATABus* ATABus::create(ATAController& controller, uint16_t base, uint16_t ctrl, uint8_t irq)
{
ATABus* bus = new ATABus(controller, base, ctrl);
ASSERT(bus);
@ -62,17 +62,20 @@ namespace Kernel
for (uint8_t i = 0; i < 2; i++)
{
m_devices[i] = new ATADevice(this);
ATADevice* device = m_devices[i];
ASSERT(device);
{
auto* temp_ptr = new ATADevice(*this);
ASSERT(temp_ptr);
m_devices[i] = BAN::RefPtr<ATADevice>::adopt(temp_ptr);
}
ATADevice& device = *m_devices[i];
BAN::ScopeGuard guard([this, i] { m_devices[i]->unref(); m_devices[i] = nullptr; });
BAN::ScopeGuard guard([this, i] { m_devices[i] = nullptr; });
auto type = identify(device, identify_buffer);
if (type == DeviceType::None)
continue;
auto res = device->initialize(type, identify_buffer);
auto res = device.initialize(type, identify_buffer);
if (res.is_error())
{
dprintln("{}", res.error());
@ -87,19 +90,19 @@ namespace Kernel
{
if (!m_devices[i])
continue;
select_device(m_devices[i]);
select_device(*m_devices[i]);
io_write(ATA_PORT_CONTROL, 0);
}
}
void ATABus::select_device(const ATADevice* device)
void ATABus::select_device(const ATADevice& device)
{
uint8_t device_index = this->device_index(device);
io_write(ATA_PORT_DRIVE_SELECT, 0xA0 | (device_index << 4));
PIT::sleep(1);
}
ATABus::DeviceType ATABus::identify(const ATADevice* device, uint16_t* buffer)
ATABus::DeviceType ATABus::identify(const ATADevice& device, uint16_t* buffer)
{
select_device(device);
@ -242,15 +245,15 @@ namespace Kernel
return BAN::Error::from_error_code(ErrorCode::None);
}
uint8_t ATABus::device_index(const ATADevice* device) const
uint8_t ATABus::device_index(const ATADevice& device) const
{
ASSERT(device == m_devices[0] || device == m_devices[1]);
return (device == m_devices[0]) ? 0 : 1;
ASSERT(&device == m_devices[0].ptr() || &device == m_devices[1].ptr());
return (&device == m_devices[0].ptr()) ? 0 : 1;
}
BAN::ErrorOr<void> ATABus::read(ATADevice* device, uint64_t lba, uint8_t sector_count, uint8_t* buffer)
BAN::ErrorOr<void> ATABus::read(ATADevice& device, uint64_t lba, uint8_t sector_count, uint8_t* buffer)
{
if (lba + sector_count > device->m_lba_count)
if (lba + sector_count > device.m_lba_count)
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
LockGuard _(m_lock);
@ -268,7 +271,7 @@ namespace Kernel
for (uint32_t sector = 0; sector < sector_count; sector++)
{
block_until_irq();
read_buffer(ATA_PORT_DATA, (uint16_t*)buffer + sector * device->m_sector_words, device->m_sector_words);
read_buffer(ATA_PORT_DATA, (uint16_t*)buffer + sector * device.m_sector_words, device.m_sector_words);
}
}
else
@ -280,9 +283,9 @@ namespace Kernel
return {};
}
BAN::ErrorOr<void> ATABus::write(ATADevice* device, uint64_t lba, uint8_t sector_count, const uint8_t* buffer)
BAN::ErrorOr<void> ATABus::write(ATADevice& device, uint64_t lba, uint8_t sector_count, const uint8_t* buffer)
{
if (lba + sector_count > device->m_lba_count)
if (lba + sector_count > device.m_lba_count)
return BAN::Error::from_error_code(ErrorCode::Storage_Boundaries);
LockGuard _(m_lock);
@ -301,7 +304,7 @@ namespace Kernel
for (uint32_t sector = 0; sector < sector_count; sector++)
{
write_buffer(ATA_PORT_DATA, (uint16_t*)buffer + sector * device->m_sector_words, device->m_sector_words);
write_buffer(ATA_PORT_DATA, (uint16_t*)buffer + sector * device.m_sector_words, device.m_sector_words);
block_until_irq();
}
}

View File

@ -1,14 +1,17 @@
#include <BAN/ScopeGuard.h>
#include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/LockGuard.h>
#include <kernel/Storage/ATABus.h>
#include <kernel/Storage/ATAController.h>
#include <kernel/Storage/ATADefinitions.h>
#include <kernel/Storage/ATADevice.h>
#include <sys/sysmacros.h>
namespace Kernel
{
BAN::ErrorOr<ATAController*> ATAController::create(const PCIDevice& device)
BAN::ErrorOr<BAN::RefPtr<ATAController>> ATAController::create(const PCIDevice& device)
{
ATAController* controller = new ATAController();
if (controller == nullptr)
@ -16,9 +19,42 @@ namespace Kernel
BAN::ScopeGuard guard([controller] { controller->unref(); });
TRY(controller->initialize(device));
guard.disable();
return controller;
auto ref_ptr = BAN::RefPtr<ATAController>::adopt(controller);
DevFileSystem::get().add_device("hd"sv, ref_ptr);
auto devices = controller->devices();
for (size_t i = 0; i < devices.size(); i++)
{
char device_name[4] { 'h', 'd', 'a', '\0' };
device_name[2] += i;
DevFileSystem::get().add_device(device_name, devices[i]);
if (auto res = devices[i]->initialize_partitions(); res.is_error())
dprintln("{}", res.error());
else
{
char partition_name[5] { 'h', 'd', 'a', '1', '\0' };
partition_name[2] += i;
auto& partitions = devices[i]->partitions();
for (size_t j = 0; j < partitions.size(); j++)
{
partition_name[3] += j;
DevFileSystem::get().add_device(partition_name, partitions[j]);
}
}
}
return ref_ptr;
}
ATAController::ATAController()
: m_rdev(makedev(DevFileSystem::get().get_next_rdev(), 0))
{ }
BAN::ErrorOr<void> ATAController::initialize(const PCIDevice& pci_device)
{
struct Bus
@ -48,21 +84,15 @@ namespace Kernel
return BAN::Error::from_error_code(ErrorCode::ATA_UnsupportedDevice);
}
m_buses[0] = ATABus::create(this, buses[0].base, buses[0].ctrl, 14);
m_buses[1] = ATABus::create(this, buses[1].base, buses[1].ctrl, 15);
m_buses[0] = ATABus::create(*this, buses[0].base, buses[0].ctrl, 14);
m_buses[1] = ATABus::create(*this, buses[1].base, buses[1].ctrl, 15);
return {};
}
uint8_t ATAController::next_device_index() const
BAN::Vector<BAN::RefPtr<StorageDevice>> ATAController::devices()
{
static uint8_t index = 0;
return index++;
}
BAN::Vector<StorageDevice*> ATAController::devices()
{
BAN::Vector<StorageDevice*> devices;
BAN::Vector<BAN::RefPtr<StorageDevice>> devices;
if (m_buses[0]->m_devices[0])
MUST(devices.push_back(m_buses[0]->m_devices[0]));
if (m_buses[0]->m_devices[1])

View File

@ -1,11 +1,19 @@
#include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/IO.h>
#include <kernel/Storage/ATABus.h>
#include <kernel/Storage/ATADefinitions.h>
#include <kernel/Storage/ATADevice.h>
#include <sys/sysmacros.h>
namespace Kernel
{
ATADevice::ATADevice(ATABus& bus)
: m_bus(bus)
, m_rdev(makedev(DevFileSystem::get().get_next_rdev(), 0))
{ }
BAN::ErrorOr<void> ATADevice::initialize(ATABus::DeviceType type, const uint16_t* identify_buffer)
{
m_type = type;
@ -45,13 +53,7 @@ namespace Kernel
}
m_model[40] = 0;
m_index = m_bus->controller()->next_device_index();
m_device_name[0] = 'h';
m_device_name[1] = 'd';
m_device_name[2] = 'a' + m_index;
m_device_name[3] = '\0';
dprintln("{} {} MB", m_device_name, total_size() / 1024 / 1024);
dprintln("ATA disk {} MB", total_size() / 1024 / 1024);
add_disk_cache();
@ -60,13 +62,13 @@ namespace Kernel
BAN::ErrorOr<void> ATADevice::read_sectors_impl(uint64_t lba, uint8_t sector_count, uint8_t* buffer)
{
TRY(m_bus->read(this, lba, sector_count, buffer));
TRY(m_bus.read(*this, lba, sector_count, buffer));
return {};
}
BAN::ErrorOr<void> ATADevice::write_sectors_impl(uint64_t lba, uint8_t sector_count, const uint8_t* buffer)
{
TRY(m_bus->write(this, lba, sector_count, buffer));
TRY(m_bus.write(*this, lba, sector_count, buffer));
return {};
}

View File

@ -7,6 +7,8 @@
#include <kernel/PCI.h>
#include <kernel/Storage/StorageDevice.h>
#include <sys/sysmacros.h>
#define ATA_DEVICE_PRIMARY 0x1F0
#define ATA_DEVICE_SECONDARY 0x170
#define ATA_DEVICE_SLAVE_BIT 0x10
@ -199,23 +201,18 @@ namespace Kernel
}
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)
: 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_index(index)
, m_device_name(BAN::String::formatted("{}{}", m_device.name(), index))
, m_rdev(makedev(major(device.rdev()), index))
{
memcpy(m_label, label, sizeof(m_label));
}
dev_t Partition::rdev() const
{
return makedev(major(m_device.rdev()), m_index);
}
BAN::ErrorOr<void> Partition::read_sectors(uint64_t lba, uint8_t sector_count, uint8_t* buffer)
{
const uint32_t sectors_in_partition = m_lba_end - m_lba_start;

View File

@ -2,12 +2,14 @@
#include <BAN/ScopeGuard.h>
#include <BAN/UTF8.h>
#include <kernel/Debug.h>
#include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/LockGuard.h>
#include <kernel/Process.h>
#include <kernel/Terminal/TTY.h>
#include <fcntl.h>
#include <string.h>
#include <sys/sysmacros.h>
#define BEL 0x07
#define BS 0x08
@ -26,7 +28,7 @@ namespace Kernel
static dev_t next_tty_rdev()
{
static dev_t major = DeviceManager::get().get_next_rdev();
static dev_t major = DevFileSystem::get().get_next_rdev();
static dev_t minor = 1;
return makedev(major, minor++);
}
@ -34,7 +36,8 @@ namespace Kernel
static TTY* s_tty = nullptr;
TTY::TTY(TerminalDriver* driver)
: m_terminal_driver(driver)
: CharacterDevice(0444, 0, 0)
, m_terminal_driver(driver)
{
m_width = m_terminal_driver->width();
m_height = m_terminal_driver->height();
@ -54,8 +57,12 @@ namespace Kernel
void TTY::initialize_device()
{
m_rdev = next_tty_rdev();
m_name = BAN::String::formatted("tty{}", minor(m_rdev));
DeviceManager::get().add_device(this);
char name[5] { 't', 't', 'y', '1', '\0'};
name[3] += minor(m_rdev);
ASSERT(minor(m_rdev) < 10);
DevFileSystem::get().add_device(name, this);
if (s_input_process)
return;

View File

@ -1,7 +1,7 @@
#include <kernel/ACPI.h>
#include <kernel/Arch.h>
#include <kernel/Debug.h>
#include <kernel/DeviceManager.h>
#include <kernel/FS/DevFS/FileSystem.h>
#include <kernel/FS/VirtualFileSystem.h>
#include <kernel/GDT.h>
#include <kernel/IDT.h>
@ -140,6 +140,9 @@ extern "C" void kernel_main()
ASSERT(terminal_driver);
dprintln("VESA initialized");
DevFileSystem::initialize();
dprintln("devfs initialized");
TTY* tty1 = new TTY(terminal_driver);
ASSERT(tty1);
dprintln("TTY initialized");
@ -147,9 +150,6 @@ extern "C" void kernel_main()
parse_command_line();
dprintln("command line parsed, root='{}'", cmdline.root);
PCI::initialize();
dprintln("PCI initialized");
MUST(ACPI::initialize());
dprintln("ACPI initialized");
@ -160,6 +160,8 @@ extern "C" void kernel_main()
dprintln("PIT initialized");
MUST(Scheduler::initialize());
dprintln("Scheduler initialized");
Scheduler& scheduler = Scheduler::get();
Process::create_kernel(init2, tty1);
scheduler.start();
@ -172,9 +174,13 @@ static void init2(void* tty1)
using namespace Kernel;
using namespace Kernel::Input;
DeviceManager::get().initialize_pci_devices();
DeviceManager::get().initialize_updater();
dprintln("Scheduler started");
DevFileSystem::get().initialize_device_updater();
PCI::initialize();
dprintln("PCI initialized");
VirtualFileSystem::initialize(cmdline.root);
if (auto res = PS2Controller::initialize(); res.is_error())