From 1baa05d6b22916c4cfdf9834dec554dd685e8a09 Mon Sep 17 00:00:00 2001 From: Liav A Date: Thu, 27 May 2021 22:03:26 +0300 Subject: [PATCH] Kernel/SysFS: Add PCI exposed folder --- Kernel/FileSystem/SysFS.cpp | 2 - Kernel/PCI/Access.cpp | 88 +++++++++++++++++++++++++++++++++++++ Kernel/PCI/Access.h | 40 ++++++++++++++++- Kernel/PCI/Initializer.cpp | 2 + 4 files changed, 128 insertions(+), 4 deletions(-) diff --git a/Kernel/FileSystem/SysFS.cpp b/Kernel/FileSystem/SysFS.cpp index 09cb9ec78dd..23d189868a1 100644 --- a/Kernel/FileSystem/SysFS.cpp +++ b/Kernel/FileSystem/SysFS.cpp @@ -13,7 +13,6 @@ namespace Kernel { -static InodeIndex s_next_inode_index; static AK::Singleton s_the; SystemRegistrar& SystemRegistrar::the() @@ -24,7 +23,6 @@ SystemRegistrar& SystemRegistrar::the() UNMAP_AFTER_INIT void SystemRegistrar::initialize() { VERIFY(!s_the.is_initialized()); - s_next_inode_index = 0; s_the.ensure_instance(); } diff --git a/Kernel/PCI/Access.cpp b/Kernel/PCI/Access.cpp index 54ddb65d38b..0796dd02331 100644 --- a/Kernel/PCI/Access.cpp +++ b/Kernel/PCI/Access.cpp @@ -368,5 +368,93 @@ void Capability::write32(u32 field, u32 value) PCI::write32(m_address, m_ptr + field, value); } +UNMAP_AFTER_INIT NonnullRefPtr ExposedDeviceFolder::create(const SystemExposedFolder& parent_folder, Address address) +{ + return adopt_ref(*new (nothrow) ExposedDeviceFolder(parent_folder, address)); +} + +UNMAP_AFTER_INIT ExposedDeviceFolder::ExposedDeviceFolder(const SystemExposedFolder& parent_folder, Address address) + : SystemExposedFolder(String::formatted("{:04x}:{:04x}:{:02x}.{}", address.seg(), address.bus(), address.device(), address.function()), parent_folder) +{ + m_components.append(ExposedAttribute::create("vendor", *this, PCI_VENDOR_ID, 2)); + m_components.append(ExposedAttribute::create("device_id", *this, PCI_DEVICE_ID, 2)); + m_components.append(ExposedAttribute::create("class", *this, PCI_CLASS, 1)); + m_components.append(ExposedAttribute::create("subclass", *this, PCI_SUBCLASS, 1)); + m_components.append(ExposedAttribute::create("revision", *this, PCI_REVISION_ID, 1)); + m_components.append(ExposedAttribute::create("progif", *this, PCI_PROG_IF, 1)); + m_components.append(ExposedAttribute::create("subsystem_vendor", *this, PCI_SUBSYSTEM_VENDOR_ID, 2)); + m_components.append(ExposedAttribute::create("subsystem_id", *this, PCI_SUBSYSTEM_ID, 2)); +} + +UNMAP_AFTER_INIT void BusExposedFolder::initialize() +{ + auto pci_folder = adopt_ref(*new (nothrow) BusExposedFolder()); + SystemRegistrar::the().register_new_component(pci_folder); +} + +UNMAP_AFTER_INIT BusExposedFolder::BusExposedFolder() + : SystemExposedFolder("pci", SystemRegistrar::the().root_folder()) +{ + PCI::enumerate([&](const Address& address, ID) { + auto pci_device = PCI::ExposedDeviceFolder::create(*this, address); + m_components.append(pci_device); + }); +} + +NonnullRefPtr ExposedAttribute::create(String name, const ExposedDeviceFolder& device, size_t offset, size_t field_bytes_width) +{ + return adopt_ref(*new (nothrow) ExposedAttribute(name, device, offset, field_bytes_width)); +} + +ExposedAttribute::ExposedAttribute(String name, const ExposedDeviceFolder& device, size_t offset, size_t field_bytes_width) + : SystemExposedComponent(name) + , m_device(device) + , m_offset(offset) + , m_field_bytes_width(field_bytes_width) +{ +} + +KResultOr ExposedAttribute::read_bytes(off_t offset, size_t count, UserOrKernelBuffer& buffer, FileDescription*) const +{ + auto blob = try_to_generate_buffer(); + if (!blob) + return KResult(EFAULT); + + if ((size_t)offset >= blob->size()) + return KSuccess; + + ssize_t nread = min(static_cast(blob->size() - offset), static_cast(count)); + if (!buffer.write(blob->data() + offset, nread)) + return KResult(EFAULT); + return nread; +} + +size_t ExposedAttribute::size() const +{ + auto buffer = try_to_generate_buffer(); + if (!buffer) + return 0; + return buffer->size(); +} + +OwnPtr ExposedAttribute::try_to_generate_buffer() const +{ + String value; + switch (m_field_bytes_width) { + case 1: + value = String::formatted("0x{:x}", PCI::read8(m_device->address(), m_offset)); + break; + case 2: + value = String::formatted("0x{:x}", PCI::read16(m_device->address(), m_offset)); + break; + case 4: + value = String::formatted("0x{:x}", PCI::read32(m_device->address(), m_offset)); + break; + default: + VERIFY_NOT_REACHED(); + } + + return KBuffer::try_create_with_bytes(value.substring_view(0).bytes()); +} } } diff --git a/Kernel/PCI/Access.h b/Kernel/PCI/Access.h index d2c12695c2d..3b42db6fd70 100644 --- a/Kernel/PCI/Access.h +++ b/Kernel/PCI/Access.h @@ -9,11 +9,47 @@ #include #include #include +#include #include -namespace Kernel { +namespace Kernel::PCI { -class PCI::Access { +class BusExposedFolder final : public SystemExposedFolder { +public: + static void initialize(); + +private: + BusExposedFolder(); +}; + +class ExposedDeviceFolder final : public SystemExposedFolder { +public: + static NonnullRefPtr create(const SystemExposedFolder&, Address); + const Address& address() const { return m_address; } + +private: + ExposedDeviceFolder(const SystemExposedFolder&, Address); + + Address m_address; +}; + +class ExposedAttribute : public SystemExposedComponent { +public: + static NonnullRefPtr create(String name, const ExposedDeviceFolder& device, size_t offset, size_t field_bytes_width); + + virtual KResultOr read_bytes(off_t, size_t, UserOrKernelBuffer&, FileDescription*) const override; + virtual ~ExposedAttribute() {}; + virtual size_t size() const override; + +protected: + virtual OwnPtr try_to_generate_buffer() const; + ExposedAttribute(String name, const ExposedDeviceFolder& device, size_t offset, size_t field_bytes_width); + NonnullRefPtr m_device; + size_t m_offset; + size_t m_field_bytes_width; +}; + +class Access { public: void enumerate(Function&) const; diff --git a/Kernel/PCI/Initializer.cpp b/Kernel/PCI/Initializer.cpp index f4074e90cea..338c6cfc813 100644 --- a/Kernel/PCI/Initializer.cpp +++ b/Kernel/PCI/Initializer.cpp @@ -51,6 +51,8 @@ UNMAP_AFTER_INIT void initialize() VERIFY_NOT_REACHED(); } + PCI::BusExposedFolder::initialize(); + PCI::enumerate([&](const Address& address, ID id) { dmesgln("{} {}", address, id); });