diff --git a/Kernel/CMakeLists.txt b/Kernel/CMakeLists.txt index 40152469cf..ad799d8ede 100644 --- a/Kernel/CMakeLists.txt +++ b/Kernel/CMakeLists.txt @@ -18,6 +18,7 @@ set(KERNEL_SOURCES CommandLine.cpp Console.cpp CoreDump.cpp + DMI.cpp Devices/AsyncDeviceRequest.cpp Devices/BXVGADevice.cpp Devices/BlockDevice.cpp diff --git a/Kernel/DMI.cpp b/Kernel/DMI.cpp new file mode 100644 index 0000000000..f542aafc53 --- /dev/null +++ b/Kernel/DMI.cpp @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2021, Liav A. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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 s_the; + +void DMIExpose::set_64_bit_entry_initialization_values() +{ + klog() << "DMIExpose: SMBIOS 64bit Entry point @ " << m_entry_point; + auto smbios_entry = map_typed(PhysicalAddress(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; +} + +void DMIExpose::set_32_bit_entry_initialization_values() +{ + klog() << "DMIExpose: SMBIOS 32bit Entry point @ " << m_entry_point; + auto smbios_entry = map_typed(PhysicalAddress(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; +} + +void DMIExpose::initialize() +{ + s_the.ensure_instance(); +} + +DMIExpose& DMIExpose::the() +{ + return *s_the; +} + +void DMIExpose::initialize_exposer() +{ + ASSERT(!(m_entry_point.is_null())); + if (m_using_64bit_entry_point) { + set_64_bit_entry_initialization_values(); + } else { + set_32_bit_entry_initialization_values(); + } + klog() << "DMIExpose: Data table @ " << m_structure_table; +} + +OwnPtr DMIExpose::entry_point() const +{ + auto dmi_blob = map_typed((m_entry_point), m_entry_point_length); + return KBuffer::try_create_with_bytes(Span { dmi_blob.ptr(), m_entry_point_length }); +} +OwnPtr DMIExpose::structure_table() const +{ + auto dmi_blob = map_typed(m_structure_table, m_structure_table_length); + return KBuffer::try_create_with_bytes(Span { dmi_blob.ptr(), m_structure_table_length }); +} + +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(); +} + +Optional DMIExpose::find_entry64bit_point() +{ + return map_bios().find_chunk_starting_with("_SM3_", 16); +} + +Optional DMIExpose::find_entry32bit_point() +{ + return map_bios().find_chunk_starting_with("_SM_", 16); +} + +} diff --git a/Kernel/DMI.h b/Kernel/DMI.h new file mode 100644 index 0000000000..660fbadfe2 --- /dev/null +++ b/Kernel/DMI.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2021, Liav A. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +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 entry_point() const; + OwnPtr structure_table() const; + +private: + void set_64_bit_entry_initialization_values(); + void set_32_bit_entry_initialization_values(); + void initialize_exposer(); + + Optional find_entry64bit_point(); + Optional 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/ProcFS.cpp b/Kernel/FileSystem/ProcFS.cpp index e1c967c6cf..6b9a1bdde2 100644 --- a/Kernel/FileSystem/ProcFS.cpp +++ b/Kernel/FileSystem/ProcFS.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -86,6 +87,8 @@ enum ProcFileType { FI_Root_cpuinfo, FI_Root_dmesg, FI_Root_interrupts, + FI_Root_dmi, + FI_Root_smbios_entry_point, FI_Root_keymap, FI_Root_pci, FI_Root_devices, @@ -377,6 +380,24 @@ static bool procfs$pci(InodeIdentifier, KBufferBuilder& builder) return true; } +static bool procfs$dmi(InodeIdentifier, KBufferBuilder& builder) +{ + if (!DMIExpose::the().is_available()) + return false; + auto structures_ptr = DMIExpose::the().structure_table(); + builder.append_bytes(ReadonlyBytes { structures_ptr->data(), structures_ptr->size() }); + return true; +} + +static bool procfs$smbios_entry_point(InodeIdentifier, KBufferBuilder& builder) +{ + if (!DMIExpose::the().is_available()) + return false; + auto structures_ptr = DMIExpose::the().entry_point(); + builder.append_bytes(ReadonlyBytes { structures_ptr->data(), structures_ptr->size() }); + return true; +} + static bool procfs$interrupts(InodeIdentifier, KBufferBuilder& builder) { JsonArraySerializer array { builder }; @@ -1628,6 +1649,8 @@ ProcFS::ProcFS() m_entries[FI_Root_self] = { "self", FI_Root_self, false, procfs$self }; m_entries[FI_Root_pci] = { "pci", FI_Root_pci, false, procfs$pci }; m_entries[FI_Root_interrupts] = { "interrupts", FI_Root_interrupts, false, procfs$interrupts }; + m_entries[FI_Root_dmi] = { "DMI", FI_Root_dmi, false, procfs$dmi }; + m_entries[FI_Root_smbios_entry_point] = { "smbios_entry_point", FI_Root_smbios_entry_point, false, procfs$smbios_entry_point }; m_entries[FI_Root_keymap] = { "keymap", FI_Root_keymap, false, procfs$keymap }; m_entries[FI_Root_devices] = { "devices", FI_Root_devices, false, procfs$devices }; m_entries[FI_Root_uptime] = { "uptime", FI_Root_uptime, false, procfs$uptime }; diff --git a/Kernel/init.cpp b/Kernel/init.cpp index c5ca51b983..5ed49bd014 100644 --- a/Kernel/init.cpp +++ b/Kernel/init.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -252,6 +253,7 @@ void init_stage2(void*) } USB::UHCIController::detect(); + DMIExpose::initialize(); E1000NetworkAdapter::detect(); RTL8139NetworkAdapter::detect();