diff options
Diffstat (limited to 'Kernel')
-rw-r--r-- | Kernel/ACPI/Parser.cpp | 73 | ||||
-rw-r--r-- | Kernel/ACPI/Parser.h | 24 | ||||
-rw-r--r-- | Kernel/Arch/PC/BIOS.cpp | 149 | ||||
-rw-r--r-- | Kernel/Arch/PC/BIOS.h | 107 | ||||
-rw-r--r-- | Kernel/CMakeLists.txt | 3 | ||||
-rw-r--r-- | Kernel/DMI.cpp | 111 | ||||
-rw-r--r-- | Kernel/DMI.h | 87 | ||||
-rw-r--r-- | Kernel/FileSystem/SysFS.cpp | 220 | ||||
-rw-r--r-- | Kernel/FileSystem/SysFS.h | 121 | ||||
-rw-r--r-- | Kernel/Syscalls/mount.cpp | 3 | ||||
-rw-r--r-- | Kernel/SystemExposed.cpp | 74 | ||||
-rw-r--r-- | Kernel/SystemExposed.h | 62 | ||||
-rw-r--r-- | Kernel/init.cpp | 7 |
13 files changed, 839 insertions, 202 deletions
diff --git a/Kernel/ACPI/Parser.cpp b/Kernel/ACPI/Parser.cpp index 1706445c7e..e86f27f33a 100644 --- a/Kernel/ACPI/Parser.cpp +++ b/Kernel/ACPI/Parser.cpp @@ -27,6 +27,79 @@ Parser* Parser::the() return s_acpi_parser; } +UNMAP_AFTER_INIT NonnullRefPtr<ExposedComponent> ExposedComponent::create(String name, PhysicalAddress paddr, size_t table_size) +{ + return adopt_ref(*new (nothrow) ExposedComponent(name, paddr, table_size)); +} + +KResultOr<size_t> ExposedComponent::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<off_t>(blob->size() - offset), static_cast<off_t>(count)); + if (!buffer.write(blob->data() + offset, nread)) + return KResult(EFAULT); + return nread; +} + +OwnPtr<KBuffer> ExposedComponent::try_to_generate_buffer() const +{ + auto acpi_blob = map_typed<u8>((m_paddr), m_length); + return KBuffer::try_create_with_bytes(Span<u8> { acpi_blob.ptr(), m_length }); +} + +UNMAP_AFTER_INIT ExposedComponent::ExposedComponent(String name, PhysicalAddress paddr, size_t table_size) + : SystemExposedComponent(name) + , m_paddr(paddr) + , m_length(table_size) +{ +} + +UNMAP_AFTER_INIT void ExposedFolder::initialize() +{ + auto acpi_folder = adopt_ref(*new (nothrow) ExposedFolder()); + SystemRegistrar::the().register_new_component(acpi_folder); +} + +UNMAP_AFTER_INIT ExposedFolder::ExposedFolder() + : SystemExposedFolder("acpi", SystemRegistrar::the().root_folder()) +{ + NonnullRefPtrVector<SystemExposedComponent> components; + size_t ssdt_count = 0; + ACPI::Parser::the()->enumerate_static_tables([&](const StringView& signature, PhysicalAddress p_table, size_t length) { + if (signature == "SSDT") { + components.append(ExposedComponent::create(String::formatted("{:4s}{}", signature.characters_without_null_termination(), ssdt_count), p_table, length)); + ssdt_count++; + return; + } + components.append(ExposedComponent::create(signature, p_table, length)); + }); + m_components = components; + + auto rsdp = map_typed<Structures::RSDPDescriptor20>(ACPI::Parser::the()->rsdp()); + m_components.append(ExposedComponent::create("RSDP", ACPI::Parser::the()->rsdp(), rsdp->base.revision == 0 ? sizeof(Structures::RSDPDescriptor) : rsdp->length)); + + auto main_system_description_table = map_typed<Structures::SDTHeader>(ACPI::Parser::the()->main_system_description_table()); + if (ACPI::Parser::the()->is_xsdt_supported()) { + m_components.append(ExposedComponent::create("XSDT", ACPI::Parser::the()->main_system_description_table(), main_system_description_table->length)); + } else { + m_components.append(ExposedComponent::create("RSDT", ACPI::Parser::the()->main_system_description_table(), main_system_description_table->length)); + } +} + +void Parser::enumerate_static_tables(Function<void(const StringView&, PhysicalAddress, size_t)> callback) +{ + for (auto& p_table : m_sdt_pointers) { + auto table = map_typed<Structures::SDTHeader>(p_table); + callback({ table->sig, 4 }, p_table, table->length); + } +} + void Parser::set_the(Parser& parser) { VERIFY(!s_acpi_parser); diff --git a/Kernel/ACPI/Parser.h b/Kernel/ACPI/Parser.h index e31e355396..c9fbd5dd2e 100644 --- a/Kernel/ACPI/Parser.h +++ b/Kernel/ACPI/Parser.h @@ -9,14 +9,36 @@ #include <AK/Types.h> #include <Kernel/ACPI/Definitions.h> #include <Kernel/ACPI/Initialize.h> -#include <Kernel/FileSystem/File.h> #include <Kernel/PhysicalAddress.h> +#include <Kernel/SystemExposed.h> #include <Kernel/VM/Region.h> #include <Kernel/VirtualAddress.h> namespace Kernel { namespace ACPI { +class ExposedFolder : public SystemExposedFolder { +public: + static void initialize(); + +private: + ExposedFolder(); +}; + +class ExposedComponent : public SystemExposedComponent { +public: + static NonnullRefPtr<ExposedComponent> create(String name, PhysicalAddress, size_t table_size); + + virtual KResultOr<size_t> read_bytes(off_t, size_t, UserOrKernelBuffer&, FileDescription*) const override; + +protected: + OwnPtr<KBuffer> try_to_generate_buffer() const; + ExposedComponent(String name, PhysicalAddress, size_t table_size); + + PhysicalAddress m_paddr; + size_t m_length; +}; + class Parser { public: static Parser* the(); diff --git a/Kernel/Arch/PC/BIOS.cpp b/Kernel/Arch/PC/BIOS.cpp index 8dd0b58dad..fc86d756d7 100644 --- a/Kernel/Arch/PC/BIOS.cpp +++ b/Kernel/Arch/PC/BIOS.cpp @@ -1,16 +1,165 @@ /* * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> + * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> * * SPDX-License-Identifier: BSD-2-Clause */ #include <AK/StringView.h> #include <Kernel/Arch/PC/BIOS.h> +#include <Kernel/FileSystem/FileDescription.h> +#include <Kernel/KBufferBuilder.h> +#include <Kernel/Sections.h> #include <Kernel/VM/MemoryManager.h> #include <Kernel/VM/TypedMapping.h> namespace Kernel { +#define SMBIOS_BASE_SEARCH_ADDR 0xf0000 +#define SMBIOS_END_SEARCH_ADDR 0xfffff +#define SMBIOS_SEARCH_AREA_SIZE (SMBIOS_END_SEARCH_ADDR - SMBIOS_BASE_SEARCH_ADDR) + +UNMAP_AFTER_INIT NonnullRefPtr<DMIEntryPointExposedBlob> DMIEntryPointExposedBlob::create(PhysicalAddress dmi_entry_point, size_t blob_size) +{ + return adopt_ref(*new (nothrow) DMIEntryPointExposedBlob(dmi_entry_point, blob_size)); +} + +UNMAP_AFTER_INIT BIOSExposedComponent::BIOSExposedComponent(String name) + : SystemExposedComponent(name) +{ +} + +KResultOr<size_t> BIOSExposedComponent::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<off_t>(blob->size() - offset), static_cast<off_t>(count)); + if (!buffer.write(blob->data() + offset, nread)) + return KResult(EFAULT); + return nread; +} + +UNMAP_AFTER_INIT DMIEntryPointExposedBlob::DMIEntryPointExposedBlob(PhysicalAddress dmi_entry_point, size_t blob_size) + : BIOSExposedComponent("smbios_entry_point") + , m_dmi_entry_point(dmi_entry_point) + , m_dmi_entry_point_length(blob_size) +{ +} + +OwnPtr<KBuffer> DMIEntryPointExposedBlob::try_to_generate_buffer() const +{ + auto dmi_blob = map_typed<u8>((m_dmi_entry_point), m_dmi_entry_point_length); + return KBuffer::try_create_with_bytes(Span<u8> { dmi_blob.ptr(), m_dmi_entry_point_length }); +} + +UNMAP_AFTER_INIT NonnullRefPtr<SMBIOSExposedTable> SMBIOSExposedTable::create(PhysicalAddress smbios_structure_table, size_t smbios_structure_table_length) +{ + return adopt_ref(*new (nothrow) SMBIOSExposedTable(smbios_structure_table, smbios_structure_table_length)); +} + +UNMAP_AFTER_INIT SMBIOSExposedTable::SMBIOSExposedTable(PhysicalAddress smbios_structure_table, size_t smbios_structure_table_length) + : BIOSExposedComponent("DMI") + , m_smbios_structure_table(smbios_structure_table) + , m_smbios_structure_table_length(smbios_structure_table_length) +{ +} + +OwnPtr<KBuffer> SMBIOSExposedTable::try_to_generate_buffer() const +{ + auto dmi_blob = map_typed<u8>((m_smbios_structure_table), m_smbios_structure_table_length); + return KBuffer::try_create_with_bytes(Span<u8> { dmi_blob.ptr(), m_smbios_structure_table_length }); +} + +UNMAP_AFTER_INIT void BIOSExposedFolder::set_dmi_64_bit_entry_initialization_values() +{ + dbgln("BIOSExposedFolder: SMBIOS 64bit Entry point @ {}", m_dmi_entry_point); + auto smbios_entry = map_typed<SMBIOS::EntryPoint64bit>(m_dmi_entry_point, SMBIOS_SEARCH_AREA_SIZE); + m_smbios_structure_table = PhysicalAddress(smbios_entry.ptr()->table_ptr); + m_dmi_entry_point_length = smbios_entry.ptr()->length; + m_smbios_structure_table_length = smbios_entry.ptr()->table_maximum_size; +} + +UNMAP_AFTER_INIT void BIOSExposedFolder::set_dmi_32_bit_entry_initialization_values() +{ + dbgln("BIOSExposedFolder: SMBIOS 32bit Entry point @ {}", m_dmi_entry_point); + auto smbios_entry = map_typed<SMBIOS::EntryPoint32bit>(m_dmi_entry_point, SMBIOS_SEARCH_AREA_SIZE); + m_smbios_structure_table = PhysicalAddress(smbios_entry.ptr()->legacy_structure.smbios_table_ptr); + m_dmi_entry_point_length = smbios_entry.ptr()->length; + m_smbios_structure_table_length = smbios_entry.ptr()->legacy_structure.smboios_table_length; +} + +UNMAP_AFTER_INIT void BIOSExposedFolder::initialize() +{ + auto bios_folder = adopt_ref(*new (nothrow) BIOSExposedFolder()); + SystemRegistrar::the().register_new_component(bios_folder); + bios_folder->create_components(); +} + +void BIOSExposedFolder::create_components() +{ + auto dmi_entry_point = DMIEntryPointExposedBlob::create(m_dmi_entry_point, m_dmi_entry_point_length); + m_components.append(dmi_entry_point); + auto smbios_table = SMBIOSExposedTable::create(m_smbios_structure_table, m_smbios_structure_table_length); + m_components.append(smbios_table); +} + +size_t BIOSExposedFolder::dmi_entry_point_length() const +{ + return m_dmi_entry_point_length; +} +size_t BIOSExposedFolder::smbios_structure_table_length() const +{ + return m_smbios_structure_table_length; +} + +UNMAP_AFTER_INIT void BIOSExposedFolder::initialize_dmi_exposer() +{ + VERIFY(!(m_dmi_entry_point.is_null())); + if (m_using_64bit_dmi_entry_point) { + set_dmi_64_bit_entry_initialization_values(); + } else { + set_dmi_32_bit_entry_initialization_values(); + } + dbgln("BIOSExposedFolder: Data table @ {}", m_smbios_structure_table); +} + +OwnPtr<KBuffer> BIOSExposedFolder::smbios_structure_table() const +{ + auto dmi_blob = map_typed<u8>(m_smbios_structure_table, m_smbios_structure_table_length); + return KBuffer::try_create_with_bytes(Span<u8> { dmi_blob.ptr(), m_smbios_structure_table_length }); +} + +UNMAP_AFTER_INIT BIOSExposedFolder::BIOSExposedFolder() + : SystemExposedFolder("bios", SystemRegistrar::the().root_folder()) +{ + auto entry_32bit = find_dmi_entry32bit_point(); + m_dmi_entry_point = entry_32bit.value(); + + auto entry_64bit = find_dmi_entry64bit_point(); + if (entry_64bit.has_value()) { + m_dmi_entry_point = entry_64bit.value(); + m_using_64bit_dmi_entry_point = true; + } + if (m_dmi_entry_point.is_null()) + return; + initialize_dmi_exposer(); +} + +UNMAP_AFTER_INIT Optional<PhysicalAddress> BIOSExposedFolder::find_dmi_entry64bit_point() +{ + return map_bios().find_chunk_starting_with("_SM3_", 16); +} + +UNMAP_AFTER_INIT Optional<PhysicalAddress> BIOSExposedFolder::find_dmi_entry32bit_point() +{ + return map_bios().find_chunk_starting_with("_SM_", 16); +} + MappedROM map_bios() { MappedROM mapping; diff --git a/Kernel/Arch/PC/BIOS.h b/Kernel/Arch/PC/BIOS.h index a3289d47b0..39bc11c73d 100644 --- a/Kernel/Arch/PC/BIOS.h +++ b/Kernel/Arch/PC/BIOS.h @@ -1,16 +1,123 @@ /* * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> + * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> * * SPDX-License-Identifier: BSD-2-Clause */ #pragma once +#include <AK/Types.h> +#include <AK/Vector.h> +#include <Kernel/FileSystem/SysFS.h> +#include <Kernel/KBuffer.h> +#include <Kernel/PhysicalAddress.h> #include <Kernel/VM/MappedROM.h> +#include <Kernel/VM/Region.h> +#include <Kernel/VirtualAddress.h> + +namespace Kernel::SMBIOS { + +struct [[gnu::packed]] LegacyEntryPoint32bit { + char legacy_sig[5]; + u8 checksum2; + u16 smboios_table_length; + u32 smbios_table_ptr; + u16 smbios_tables_count; + u8 smbios_bcd_revision; +}; + +struct [[gnu::packed]] EntryPoint32bit { + char sig[4]; + u8 checksum; + u8 length; + u8 major_version; + u8 minor_version; + u16 maximum_structure_size; + u8 implementation_revision; + char formatted_area[5]; + LegacyEntryPoint32bit legacy_structure; +}; + +struct [[gnu::packed]] EntryPoint64bit { + char sig[5]; + u8 checksum; + u8 length; + u8 major_version; + u8 minor_version; + u8 document_revision; + u8 revision; + u8 reserved; + u32 table_maximum_size; + u64 table_ptr; +}; +} namespace Kernel { MappedROM map_bios(); MappedROM map_ebda(); +class BIOSExposedComponent : public SystemExposedComponent { +public: + virtual KResultOr<size_t> read_bytes(off_t, size_t, UserOrKernelBuffer&, FileDescription*) const override; + +protected: + virtual OwnPtr<KBuffer> try_to_generate_buffer() const = 0; + explicit BIOSExposedComponent(String name); +}; + +class DMIEntryPointExposedBlob : public BIOSExposedComponent { +public: + static NonnullRefPtr<DMIEntryPointExposedBlob> create(PhysicalAddress dmi_entry_point, size_t blob_size); + virtual size_t size() const override { return m_dmi_entry_point_length; } + +private: + DMIEntryPointExposedBlob(PhysicalAddress dmi_entry_point, size_t blob_size); + virtual OwnPtr<KBuffer> try_to_generate_buffer() const override; + PhysicalAddress m_dmi_entry_point; + size_t m_dmi_entry_point_length; +}; + +class SMBIOSExposedTable : public BIOSExposedComponent { +public: + static NonnullRefPtr<SMBIOSExposedTable> create(PhysicalAddress, size_t blob_size); + virtual size_t size() const override { return m_smbios_structure_table_length; } + +private: + SMBIOSExposedTable(PhysicalAddress dmi_entry_point, size_t blob_size); + virtual OwnPtr<KBuffer> try_to_generate_buffer() const override; + + PhysicalAddress m_smbios_structure_table; + size_t m_smbios_structure_table_length; +}; + +class BIOSExposedFolder : public SystemExposedFolder { +public: + static void initialize(); + + void create_components(); + +private: + OwnPtr<KBuffer> dmi_entry_point() const; + OwnPtr<KBuffer> smbios_structure_table() const; + size_t dmi_entry_point_length() const; + size_t smbios_structure_table_length() const; + + BIOSExposedFolder(); + + void set_dmi_64_bit_entry_initialization_values(); + void set_dmi_32_bit_entry_initialization_values(); + void initialize_dmi_exposer(); + + Optional<PhysicalAddress> find_dmi_entry64bit_point(); + Optional<PhysicalAddress> find_dmi_entry32bit_point(); + + PhysicalAddress m_dmi_entry_point; + PhysicalAddress m_smbios_structure_table; + bool m_using_64bit_dmi_entry_point { false }; + size_t m_smbios_structure_table_length { 0 }; + size_t m_dmi_entry_point_length { 0 }; +}; + } diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index d991bac2e9..9652fbace8 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -30,7 +30,6 @@ set(KERNEL_SOURCES CommandLine.cpp ConsoleDevice.cpp CoreDump.cpp - DMI.cpp Devices/AsyncDeviceRequest.cpp Devices/BlockDevice.cpp Devices/CharacterDevice.cpp @@ -107,6 +106,7 @@ set(KERNEL_SOURCES FileSystem/InodeWatcher.cpp FileSystem/Plan9FileSystem.cpp FileSystem/ProcFS.cpp + FileSystem/SysFS.cpp FileSystem/TmpFS.cpp FileSystem/VirtualFileSystem.cpp FutexQueue.cpp @@ -225,6 +225,7 @@ set(KERNEL_SOURCES Syscalls/waitid.cpp Syscalls/inode_watcher.cpp Syscalls/write.cpp + SystemExposed.cpp TTY/ConsoleManagement.cpp TTY/MasterPTY.cpp TTY/PTYMultiplexer.cpp diff --git a/Kernel/DMI.cpp b/Kernel/DMI.cpp deleted file mode 100644 index 8d821c3287..0000000000 --- a/Kernel/DMI.cpp +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#include <AK/Format.h> -#include <AK/Singleton.h> -#include <AK/StringView.h> -#include <AK/Types.h> -#include <Kernel/Arch/PC/BIOS.h> -#include <Kernel/DMI.h> -#include <Kernel/Sections.h> -#include <Kernel/StdLib.h> -#include <Kernel/VM/MappedROM.h> -#include <Kernel/VM/TypedMapping.h> - -namespace Kernel { - -#define SMBIOS_BASE_SEARCH_ADDR 0xf0000 -#define SMBIOS_END_SEARCH_ADDR 0xfffff -#define SMBIOS_SEARCH_AREA_SIZE (SMBIOS_END_SEARCH_ADDR - SMBIOS_BASE_SEARCH_ADDR) - -AK::Singleton<DMIExpose> s_the; - -UNMAP_AFTER_INIT void DMIExpose::set_64_bit_entry_initialization_values() -{ - dbgln("DMIExpose: SMBIOS 64bit Entry point @ {}", m_entry_point); - auto smbios_entry = map_typed<SMBIOS::EntryPoint64bit>(m_entry_point, SMBIOS_SEARCH_AREA_SIZE); - m_structure_table = PhysicalAddress(smbios_entry.ptr()->table_ptr); - m_entry_point_length = smbios_entry.ptr()->length; - m_structure_table_length = smbios_entry.ptr()->table_maximum_size; -} - -UNMAP_AFTER_INIT void DMIExpose::set_32_bit_entry_initialization_values() -{ - dbgln("DMIExpose: SMBIOS 32bit Entry point @ {}", m_entry_point); - auto smbios_entry = map_typed<SMBIOS::EntryPoint32bit>(m_entry_point, SMBIOS_SEARCH_AREA_SIZE); - m_structure_table = PhysicalAddress(smbios_entry.ptr()->legacy_structure.smbios_table_ptr); - m_entry_point_length = smbios_entry.ptr()->length; - m_structure_table_length = smbios_entry.ptr()->legacy_structure.smboios_table_length; -} - -UNMAP_AFTER_INIT void DMIExpose::initialize() -{ - s_the.ensure_instance(); -} - -DMIExpose& DMIExpose::the() -{ - return *s_the; -} - -size_t DMIExpose::entry_point_length() const -{ - return m_entry_point_length; -} -size_t DMIExpose::structure_table_length() const -{ - return m_structure_table_length; -} - -UNMAP_AFTER_INIT void DMIExpose::initialize_exposer() -{ - VERIFY(!(m_entry_point.is_null())); - if (m_using_64bit_entry_point) { - set_64_bit_entry_initialization_values(); - } else { - set_32_bit_entry_initialization_values(); - } - dbgln("DMIExpose: Data table @ {}", m_structure_table); -} - -OwnPtr<KBuffer> DMIExpose::entry_point() const -{ - auto dmi_blob = map_typed<u8>((m_entry_point), m_entry_point_length); - return KBuffer::try_create_with_bytes(Span<u8> { dmi_blob.ptr(), m_entry_point_length }); -} -OwnPtr<KBuffer> DMIExpose::structure_table() const -{ - auto dmi_blob = map_typed<u8>(m_structure_table, m_structure_table_length); - return KBuffer::try_create_with_bytes(Span<u8> { dmi_blob.ptr(), m_structure_table_length }); -} - -UNMAP_AFTER_INIT DMIExpose::DMIExpose() -{ - auto entry_32bit = find_entry32bit_point(); - m_entry_point = entry_32bit.value(); - - auto entry_64bit = find_entry64bit_point(); - if (entry_64bit.has_value()) { - m_entry_point = entry_64bit.value(); - m_using_64bit_entry_point = true; - } - if (m_entry_point.is_null()) - return; - m_available = true; - initialize_exposer(); -} - -UNMAP_AFTER_INIT Optional<PhysicalAddress> DMIExpose::find_entry64bit_point() -{ - return map_bios().find_chunk_starting_with("_SM3_", 16); -} - -UNMAP_AFTER_INIT Optional<PhysicalAddress> DMIExpose::find_entry32bit_point() -{ - return map_bios().find_chunk_starting_with("_SM_", 16); -} - -} diff --git a/Kernel/DMI.h b/Kernel/DMI.h deleted file mode 100644 index 90c0cee305..0000000000 --- a/Kernel/DMI.h +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> - * - * SPDX-License-Identifier: BSD-2-Clause - */ - -#pragma once - -#include <AK/SinglyLinkedList.h> -#include <AK/Types.h> -#include <AK/Vector.h> -#include <Kernel/KBuffer.h> -#include <Kernel/PhysicalAddress.h> -#include <Kernel/VM/Region.h> -#include <Kernel/VirtualAddress.h> - -namespace Kernel::SMBIOS { - -struct [[gnu::packed]] LegacyEntryPoint32bit { - char legacy_sig[5]; - u8 checksum2; - u16 smboios_table_length; - u32 smbios_table_ptr; - u16 smbios_tables_count; - u8 smbios_bcd_revision; -}; - -struct [[gnu::packed]] EntryPoint32bit { - char sig[4]; - u8 checksum; - u8 length; - u8 major_version; - u8 minor_version; - u16 maximum_structure_size; - u8 implementation_revision; - char formatted_area[5]; - LegacyEntryPoint32bit legacy_structure; -}; - -struct [[gnu::packed]] EntryPoint64bit { - char sig[5]; - u8 checksum; - u8 length; - u8 major_version; - u8 minor_version; - u8 document_revision; - u8 revision; - u8 reserved; - u32 table_maximum_size; - u64 table_ptr; -}; -} - -namespace Kernel { - -class DMIExpose { - -public: - static void initialize(); - - DMIExpose(); - - static DMIExpose& the(); - - bool is_available() const { return m_available; } - OwnPtr<KBuffer> entry_point() const; - OwnPtr<KBuffer> structure_table() const; - size_t entry_point_length() const; - size_t structure_table_length() const; - -private: - void set_64_bit_entry_initialization_values(); - void set_32_bit_entry_initialization_values(); - void initialize_exposer(); - - Optional<PhysicalAddress> find_entry64bit_point(); - Optional<PhysicalAddress> find_entry32bit_point(); - - PhysicalAddress m_entry_point; - PhysicalAddress m_structure_table; - bool m_using_64bit_entry_point { false }; - bool m_available { false }; - size_t m_structure_table_length { 0 }; - size_t m_entry_point_length { 0 }; -}; - -} diff --git a/Kernel/FileSystem/SysFS.cpp b/Kernel/FileSystem/SysFS.cpp new file mode 100644 index 0000000000..09cb9ec78d --- /dev/null +++ b/Kernel/FileSystem/SysFS.cpp @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <AK/Singleton.h> +#include <AK/StringBuilder.h> +#include <AK/StringView.h> +#include <Kernel/FileSystem/SysFS.h> +#include <Kernel/FileSystem/VirtualFileSystem.h> +#include <Kernel/Sections.h> + +namespace Kernel { + +static InodeIndex s_next_inode_index; +static AK::Singleton<SystemRegistrar> s_the; + +SystemRegistrar& SystemRegistrar::the() +{ + return *s_the; +} + +UNMAP_AFTER_INIT void SystemRegistrar::initialize() +{ + VERIFY(!s_the.is_initialized()); + s_next_inode_index = 0; + s_the.ensure_instance(); +} + +UNMAP_AFTER_INIT SystemRegistrar::SystemRegistrar() + : m_root_folder(SysFSRootFolder::create()) +{ +} + +UNMAP_AFTER_INIT void SystemRegistrar::register_new_component(SystemExposedComponent& component) +{ + Locker locker(m_lock); + m_root_folder->m_components.append(component); +} + +NonnullRefPtr<SysFSRootFolder> SysFSRootFolder::create() +{ + return adopt_ref(*new (nothrow) SysFSRootFolder); +} + +KResult SysFSRootFolder::traverse_as_directory(unsigned fsid, Function<bool(const FS::DirectoryEntryView&)> callback) const +{ + Locker locker(SystemRegistrar::the().m_lock); + callback({ ".", { fsid, component_index() }, 0 }); + callback({ "..", { fsid, 0 }, 0 }); + + for (auto& component : m_components) { + InodeIdentifier identifier = { fsid, component.component_index() }; + callback({ component.name(), identifier, 0 }); + } + return KSuccess; +} + +SysFSRootFolder::SysFSRootFolder() + : SystemExposedFolder(".") +{ +} + +NonnullRefPtr<SysFS> SysFS::create() +{ + return adopt_ref(*new (nothrow) SysFS); +} + +SysFS::SysFS() + : m_root_inode(SystemRegistrar::the().m_root_folder->to_inode(*this)) +{ + Locker locker(m_lock); +} + +SysFS::~SysFS() +{ +} + +bool SysFS::initialize() +{ + return true; +} + +NonnullRefPtr<Inode> SysFS::root_inode() const +{ + return *m_root_inode; +} + +NonnullRefPtr<SysFSInode> SysFSInode::create(const SysFS& fs, const SystemExposedComponent& component) +{ + return adopt_ref(*new (nothrow) SysFSInode(fs, component)); +} + +SysFSInode::SysFSInode(const SysFS& fs, const SystemExposedComponent& component) + : Inode(const_cast<SysFS&>(fs), component.component_index()) + , m_associated_component(component) +{ +} + +KResultOr<size_t> SysFSInode::read_bytes(off_t offset, size_t count, UserOrKernelBuffer& buffer, FileDescription* fd) const +{ + return m_associated_component->read_bytes(offset, count, buffer, fd); +} + +KResult SysFSInode::traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)>) const +{ + VERIFY_NOT_REACHED(); +} + +RefPtr<Inode> SysFSInode::lookup(StringView) +{ + VERIFY_NOT_REACHED(); +} + +InodeMetadata SysFSInode::metadata() const +{ + Locker locker(m_lock); + InodeMetadata metadata; + metadata.inode = { fsid(), m_associated_component->component_index() }; + metadata.mode = S_IFREG | S_IRUSR | S_IRGRP | S_IROTH; + metadata.uid = 0; + metadata.gid = 0; + metadata.size = m_associated_component->size(); + metadata.mtime = mepoch; + return metadata; +} + +void SysFSInode::flush_metadata() +{ +} + +KResultOr<size_t> SysFSInode::write_bytes(off_t offset, size_t count, const UserOrKernelBuffer& buffer, FileDescription* fd) +{ + return m_associated_component->write_bytes(offset, count, buffer, fd); +} + +KResultOr<NonnullRefPtr<Inode>> SysFSInode::create_child(const String&, mode_t, dev_t, uid_t, gid_t) +{ + return EROFS; +} + +KResult SysFSInode::add_child(Inode&, const StringView&, mode_t) +{ + return EROFS; +} + +KResult SysFSInode::remove_child(const StringView&) +{ + return EROFS; +} + +KResultOr<size_t> SysFSInode::directory_entry_count() const +{ + VERIFY_NOT_REACHED(); +} + +KResult SysFSInode::chmod(mode_t) +{ + return EPERM; +} + +KResult SysFSInode::chown(uid_t, gid_t) +{ + return EPERM; +} + +KResult SysFSInode::truncate(u64) +{ + return EPERM; +} + +NonnullRefPtr<SysFSDirectoryInode> SysFSDirectoryInode::create(const SysFS& sysfs, const SystemExposedComponent& component) +{ + return adopt_ref(*new (nothrow) SysFSDirectoryInode(sysfs, component)); +} + +SysFSDirectoryInode::SysFSDirectoryInode(const SysFS& fs, const SystemExposedComponent& component) + : SysFSInode(fs, component) + , m_parent_fs(const_cast<SysFS&>(fs)) +{ +} + +SysFSDirectoryInode::~SysFSDirectoryInode() +{ +} +InodeMetadata SysFSDirectoryInode::metadata() const +{ + Locker locker(m_lock); + InodeMetadata metadata; + metadata.inode = { fsid(), m_associated_component->component_index() }; + metadata.mode = S_IFDIR | S_IRUSR | S_IRGRP | S_IROTH | S_IXOTH; + metadata.uid = 0; + metadata.gid = 0; + metadata.size = 0; + metadata.mtime = mepoch; + return metadata; +} +KResult SysFSDirectoryInode::traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)> callback) const +{ + Locker locker(m_parent_fs.m_lock); + return m_associated_component->traverse_as_directory(m_parent_fs.fsid(), move(callback)); +} + +RefPtr<Inode> SysFSDirectoryInode::lookup(StringView name) +{ + Locker locker(m_parent_fs.m_lock); + auto component = m_associated_component->lookup(name); + if (!component) + return {}; + return component->to_inode(m_parent_fs); +} + +KResultOr<size_t> SysFSDirectoryInode::directory_entry_count() const +{ + Locker locker(m_lock); + return m_associated_component->entries_count(); +} + +} diff --git a/Kernel/FileSystem/SysFS.h b/Kernel/FileSystem/SysFS.h new file mode 100644 index 0000000000..97269d624a --- /dev/null +++ b/Kernel/FileSystem/SysFS.h @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/Singleton.h> +#include <AK/String.h> +#include <AK/Types.h> +#include <Kernel/FileSystem/FileSystem.h> +#include <Kernel/FileSystem/Inode.h> +#include <Kernel/FileSystem/InodeMetadata.h> +#include <Kernel/SystemExposed.h> +#include <Kernel/TTY/SlavePTY.h> + +namespace Kernel { + +class SysFS; +class SysFSInode; +class SysFSDirectoryInode; + +class SysFSRootFolder final : public SystemExposedFolder { + friend class SystemRegistrar; + +public: + static NonnullRefPtr<SysFSRootFolder> create(); + virtual KResult traverse_as_directory(unsigned, Function<bool(const FS::DirectoryEntryView&)>) const override; + +private: + SysFSRootFolder(); +}; + +class SystemRegistrar { + friend class SysFS; + friend class SystemExposedComponent; + friend class SystemExposedFolder; + friend class SysFSRootFolder; + +public: + static SystemRegistrar& the(); + + static void initialize(); + + SystemRegistrar(); + void register_new_component(SystemExposedComponent&); + + NonnullRefPtr<SystemExposedFolder> root_folder() { return m_root_folder; } + +private: + Lock m_lock; + NonnullRefPtr<SysFSRootFolder> m_root_folder; +}; + +class SysFS final : public FS { + friend class SysFSInode; + friend class SysFSDirectoryInode; + +public: + virtual ~SysFS() override; + static NonnullRefPtr<SysFS> create(); + + virtual bool initialize() override; + virtual const char* class_name() const override { return "SysFS"; } + + virtual NonnullRefPtr<Inode> root_inode() const override; + +private: + SysFS(); + + NonnullRefPtr<SysFSInode> m_root_inode; +}; + +class SysFSInode : public Inode { + friend class SysFS; + friend class SysFSDirectoryInode; + +public: + static NonnullRefPtr<SysFSInode> create(const SysFS&, const SystemExposedComponent&); + StringView name() const { return m_associated_component->name(); } + +protected: + SysFSInode(const SysFS&, const SystemExposedComponent&); + virtual KResultOr<size_t> read_bytes(off_t, size_t, UserOrKernelBuffer& buffer, FileDescription*) const override; + virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)>) const override; + virtual RefPtr<Inode> lookup(StringView name) override; + virtual void flush_metadata() override; + virtual InodeMetadata metadata() const override; + virtual KResultOr<size_t> write_bytes(off_t, size_t, const UserOrKernelBuffer& buffer, FileDescription*) override; + virtual KResultOr<NonnullRefPtr<Inode>> create_child(const String& name, mode_t, dev_t, uid_t, gid_t) override; + virtual KResult add_child(Inode&, const StringView& name, mode_t) override; + virtual KResult remove_child(const StringView& name) override; + virtual KResultOr<size_t> directory_entry_count() const override; + virtual KResult chmod(mode_t) override; + virtual KResult chown(uid_t, gid_t) override; + virtual KResult truncate(u64) override; + + NonnullRefPtr<SystemExposedComponent> m_associated_component; +}; + +class SysFSDirectoryInode : public SysFSInode { + friend class SysFS; + friend class SysFSRootDirectoryInode; + +public: + static NonnullRefPtr<SysFSDirectoryInode> create(const SysFS&, const SystemExposedComponent&); + virtual ~SysFSDirectoryInode() override; + +protected: + SysFSDirectoryInode(const SysFS&, const SystemExposedComponent&); + // ^Inode + virtual InodeMetadata metadata() const override; + virtual KResult traverse_as_directory(Function<bool(const FS::DirectoryEntryView&)>) const override; + virtual RefPtr<Inode> lookup(StringView name) override; + virtual KResultOr<size_t> directory_entry_count() const override; + + SysFS& m_parent_fs; +}; + +} diff --git a/Kernel/Syscalls/mount.cpp b/Kernel/Syscalls/mount.cpp index c6b9f7c5b8..f42c1bb213 100644 --- a/Kernel/Syscalls/mount.cpp +++ b/Kernel/Syscalls/mount.cpp @@ -10,6 +10,7 @@ #include <Kernel/FileSystem/Ext2FileSystem.h> #include <Kernel/FileSystem/Plan9FileSystem.h> #include <Kernel/FileSystem/ProcFS.h> +#include <Kernel/FileSystem/SysFS.h> #include <Kernel/FileSystem/TmpFS.h> #include <Kernel/FileSystem/VirtualFileSystem.h> #include <Kernel/Process.h> @@ -89,6 +90,8 @@ KResultOr<FlatPtr> Process::sys$mount(Userspace<const Syscall::SC_mount_params*> fs = DevPtsFS::create(); } else if (fs_type == "dev" || fs_type == "DevFS") { fs = DevFS::create(); + } else if (fs_type == "sys" || fs_type == "SysFS") { + fs = SysFS::create(); } else if (fs_type == "tmp" || fs_type == "TmpFS") { fs = TmpFS::create(); } else { diff --git a/Kernel/SystemExposed.cpp b/Kernel/SystemExposed.cpp new file mode 100644 index 0000000000..12598dad7d --- /dev/null +++ b/Kernel/SystemExposed.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include <Kernel/FileSystem/SysFS.h> +#include <Kernel/SystemExposed.h> + +namespace Kernel { + +static SpinLock<u8> s_index_lock; +static InodeIndex s_next_inode_index { 0 }; + +static size_t allocate_inode_index() +{ + ScopedSpinLock lock(s_index_lock); + s_next_inode_index = s_next_inode_index.value() + 1; + VERIFY(s_next_inode_index > 0); + return s_next_inode_index.value(); +} + +SystemExposedComponent::SystemExposedComponent(StringView name) + : m_name(KString::try_create(name).release_nonnull()) + , m_component_index(allocate_inode_index()) +{ +} + +KResult SystemExposedFolder::traverse_as_directory(unsigned fsid, Function<bool(const FS::DirectoryEntryView&)> callback) const +{ + Locker locker(SystemRegistrar::the().m_lock); + VERIFY(m_parent_folder); + callback({ ".", { fsid, component_index() }, 0 }); + callback({ "..", { fsid, m_parent_folder->component_index() }, 0 }); + + for (auto& component : m_components) { + InodeIdentifier identifier = { fsid, component.component_index() }; + callback({ component.name(), identifier, 0 }); + } + return KSuccess; +} + +RefPtr<SystemExposedComponent> SystemExposedFolder::lookup(StringView name) +{ + for (auto& component : m_components) { + if (component.name() == name) { + return component; + } + } + return {}; +} + +SystemExposedFolder::SystemExposedFolder(String name) + : SystemExposedComponent(name) +{ +} + +SystemExposedFolder::SystemExposedFolder(String name, const SystemExposedFolder& parent_folder) + : SystemExposedComponent(name) + , m_parent_folder(parent_folder) +{ +} + +NonnullRefPtr<Inode> SystemExposedFolder::to_inode(const SysFS& sysfs_instance) const +{ + return SysFSDirectoryInode::create(sysfs_instance, *this); +} + +NonnullRefPtr<Inode> SystemExposedComponent::to_inode(const SysFS& sysfs_instance) const +{ + return SysFSInode::create(sysfs_instance, *this); +} + +} diff --git a/Kernel/SystemExposed.h b/Kernel/SystemExposed.h new file mode 100644 index 0000000000..6ef0f29305 --- /dev/null +++ b/Kernel/SystemExposed.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2021, Liav A. <liavalb@hotmail.co.il> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <AK/Function.h> +#include <AK/RefCounted.h> +#include <AK/RefPtr.h> +#include <AK/String.h> +#include <AK/Types.h> +#include <Kernel/FileSystem/File.h> +#include <Kernel/FileSystem/FileSystem.h> +#include <Kernel/KResult.h> +#include <Kernel/UserOrKernelBuffer.h> + +namespace Kernel { + +class SysFS; +class SystemExposedComponent : public RefCounted<SystemExposedComponent> { +public: + virtual KResultOr<size_t> entries_count() const { VERIFY_NOT_REACHED(); }; + virtual StringView name() const { return m_name->view(); } + virtual KResultOr<size_t> read_bytes(off_t, size_t, UserOrKernelBuffer&, FileDescription*) const { VERIFY_NOT_REACHED(); } + virtual KResult traverse_as_directory(unsigned, Function<bool(const FS::DirectoryEntryView&)>) const { VERIFY_NOT_REACHED(); } + virtual RefPtr<SystemExposedComponent> lookup(StringView) { VERIFY_NOT_REACHED(); }; + virtual KResultOr<size_t> write_bytes(off_t, size_t, const UserOrKernelBuffer&, FileDescription*) { return -EROFS; } + virtual size_t size() const { return 0; } + + virtual NonnullRefPtr<Inode> to_inode(const SysFS& sysfs_instance) const; + + size_t component_index() const { return m_component_index; }; + + virtual ~SystemExposedComponent() = default; + +protected: + explicit SystemExposedComponent(StringView name); + +private: + NonnullOwnPtr<KString> m_name; + size_t m_component_index; +}; + +class SystemExposedFolder : public SystemExposedComponent { +public: + virtual KResultOr<size_t> entries_count() const override { return m_components.size(); }; + virtual KResult traverse_as_directory(unsigned, Function<bool(const FS::DirectoryEntryView&)>) const override; + virtual RefPtr<SystemExposedComponent> lookup(StringView name) override; + void add_component(const SystemExposedComponent&); + + virtual NonnullRefPtr<Inode> to_inode(const SysFS& sysfs_instance) const override final; + +protected: + explicit SystemExposedFolder(String name); + SystemExposedFolder(String name, const SystemExposedFolder& parent_folder); + NonnullRefPtrVector<SystemExposedComponent> m_components; + RefPtr<SystemExposedFolder> m_parent_folder; +}; + +} diff --git a/Kernel/init.cpp b/Kernel/init.cpp index f67bb8bd86..10e4e8b1eb 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -9,9 +9,9 @@ #include <Kernel/ACPI/Initialize.h> #include <Kernel/ACPI/MultiProcessorParser.h> #include <Kernel/Arch/x86/Processor.h> +#include <Kernel/Arch/PC/BIOS.h> #include <Kernel/CMOS.h> #include <Kernel/CommandLine.h> -#include <Kernel/DMI.h> #include <Kernel/Devices/FullDevice.h> #include <Kernel/Devices/HID/HIDManagement.h> #include <Kernel/Devices/MemoryDevice.h> @@ -24,6 +24,7 @@ #include <Kernel/Devices/VMWareBackdoor.h> #include <Kernel/Devices/ZeroDevice.h> #include <Kernel/FileSystem/Ext2FileSystem.h> +#include <Kernel/FileSystem/SysFS.h> #include <Kernel/FileSystem/VirtualFileSystem.h> #include <Kernel/Graphics/GraphicsManagement.h> #include <Kernel/Heap/SlabAllocator.h> @@ -146,6 +147,7 @@ extern "C" [[noreturn]] UNMAP_AFTER_INIT void init() ACPI::initialize(); // Initialize the PCI Bus as early as possible, for early boot (PCI based) serial logging + SystemRegistrar::initialize(); PCI::initialize(); PCISerialDevice::detect(); @@ -237,7 +239,8 @@ void init_stage2(void*) USB::UHCIController::detect(); - DMIExpose::initialize(); + BIOSExposedFolder::initialize(); + ACPI::ExposedFolder::initialize(); VirtIO::detect(); |