diff options
author | Liav A <liavalb@gmail.com> | 2019-12-31 13:01:09 +0200 |
---|---|---|
committer | Andreas Kling <awesomekling@gmail.com> | 2020-01-02 00:50:09 +0100 |
commit | 1e1a6a57edab2919206d6219ec8c0ff1cb97ce97 (patch) | |
tree | 85b78e1e42cef61becfa33c5a6fcccd1badab912 /Kernel | |
parent | 331f37d1a8514d537928cd13a0761b37d8dce74b (diff) | |
download | serenity-1e1a6a57edab2919206d6219ec8c0ff1cb97ce97.zip |
Kernel: Introduce the ACPI subsystem
ACPI subsystem includes 3 types of parsers that are created during
runtime, each one capable of parsing ACPI tables at different level.
ACPIParser is the most basic parser which is essentialy a parser that
can't parse anything useful, due to a user request to disable ACPI
support in a kernel boot parameter.
ACPIStaticParser is a derived class from ACPIParser, which is able to
parse only static data (e.g. FADT, HPET, MCFG and other tables), thus
making it not able to parse AML (ACPI Machine Language) nor to support
handling of hardware events and power management. This type of parser
can be created with a kernel boot parameter.
ACPIDynamicParser is a derived class from ACPIStaticParser, which
includes all the capabilities of the latter, but *should* implement an
AML interpretation, (by building the ACPI AML namespace) and handling
power & hardware events. Currently the methods to support AML
interpretation are not implemented.
This type of parser is created automatically during runtime if the user
didn't specify a boot parameter related to ACPI initialization.
Also, adding strncmp function definition in StdLib.h, to be able to use
it in ACPIStaticParser class.
Diffstat (limited to 'Kernel')
-rw-r--r-- | Kernel/ACPI/ACPIDynamicParser.cpp | 67 | ||||
-rw-r--r-- | Kernel/ACPI/ACPIDynamicParser.h | 33 | ||||
-rw-r--r-- | Kernel/ACPI/ACPIParser.cpp | 84 | ||||
-rw-r--r-- | Kernel/ACPI/ACPIParser.h | 33 | ||||
-rw-r--r-- | Kernel/ACPI/ACPIStaticParser.cpp | 372 | ||||
-rw-r--r-- | Kernel/ACPI/ACPIStaticParser.h | 42 | ||||
-rw-r--r-- | Kernel/ACPI/Definitions.h | 262 | ||||
-rw-r--r-- | Kernel/StdLib.h | 1 |
8 files changed, 894 insertions, 0 deletions
diff --git a/Kernel/ACPI/ACPIDynamicParser.cpp b/Kernel/ACPI/ACPIDynamicParser.cpp new file mode 100644 index 0000000000..8d6d3e7385 --- /dev/null +++ b/Kernel/ACPI/ACPIDynamicParser.cpp @@ -0,0 +1,67 @@ +#include <Kernel/ACPI/ACPIDynamicParser.h> +#include <Kernel/ACPI/ACPIParser.h> + +void ACPIDynamicParser::initialize(ACPI_RAW::RSDPDescriptor20& rsdp) +{ + if (!ACPIStaticParser::is_initialized()) { + new ACPIDynamicParser(rsdp); + } +} +void ACPIDynamicParser::initialize_without_rsdp() +{ + if (!ACPIStaticParser::is_initialized()) { + new ACPIDynamicParser(); + } +} + +ACPIDynamicParser::ACPIDynamicParser() + : IRQHandler(9) + , ACPIStaticParser() + +{ + kprintf("ACPI: Dynamic Parsing Enabled, Can parse AML\n"); +} +ACPIDynamicParser::ACPIDynamicParser(ACPI_RAW::RSDPDescriptor20& rsdp) + : IRQHandler(9) + , ACPIStaticParser(rsdp) +{ + kprintf("ACPI: Dynamic Parsing Enabled, Can parse AML\n"); +} + +void ACPIDynamicParser::handle_irq() +{ + // FIXME: Implement IRQ handling of ACPI signals! + ASSERT_NOT_REACHED(); +} + +void ACPIDynamicParser::enable_aml_interpretation() +{ + // FIXME: Implement AML Interpretation + ASSERT_NOT_REACHED(); +} +void ACPIDynamicParser::enable_aml_interpretation(File&) +{ + // FIXME: Implement AML Interpretation + ASSERT_NOT_REACHED(); +} +void ACPIDynamicParser::enable_aml_interpretation(u8*, u32) +{ + // FIXME: Implement AML Interpretation + ASSERT_NOT_REACHED(); +} +void ACPIDynamicParser::disable_aml_interpretation() +{ + // FIXME: Implement AML Interpretation + ASSERT_NOT_REACHED(); +} +void ACPIDynamicParser::do_acpi_shutdown() +{ + // FIXME: Implement AML Interpretation to perform ACPI shutdown + ASSERT_NOT_REACHED(); +} + +void ACPIDynamicParser::build_namespace() +{ + // FIXME: Implement AML Interpretation to build the ACPI namespace + ASSERT_NOT_REACHED(); +}
\ No newline at end of file diff --git a/Kernel/ACPI/ACPIDynamicParser.h b/Kernel/ACPI/ACPIDynamicParser.h new file mode 100644 index 0000000000..4c3101fbf8 --- /dev/null +++ b/Kernel/ACPI/ACPIDynamicParser.h @@ -0,0 +1,33 @@ +#pragma once + +#include <AK/RefPtr.h> +#include <Kernel/ACPI/ACPIStaticParser.h> +#include <Kernel/Devices/DiskDevice.h> +#include <Kernel/IRQHandler.h> +#include <Kernel/Lock.h> +#include <Kernel/VM/PhysicalAddress.h> +#include <Kernel/VM/PhysicalPage.h> + +class ACPIDynamicParser final : public IRQHandler + , ACPIStaticParser { +public: + static void initialize(ACPI_RAW::RSDPDescriptor20& rsdp); + static void initialize_without_rsdp(); + + virtual void enable_aml_interpretation() override; + virtual void enable_aml_interpretation(File& dsdt_file) override; + virtual void enable_aml_interpretation(u8* physical_dsdt, u32 dsdt_payload_legnth) override; + virtual void disable_aml_interpretation() override; + virtual void do_acpi_shutdown() override; + +protected: + ACPIDynamicParser(); + explicit ACPIDynamicParser(ACPI_RAW::RSDPDescriptor20&); + +private: + void build_namespace(); + // ^IRQHandler + virtual void handle_irq() override; + + OwnPtr<Region> m_acpi_namespace; +};
\ No newline at end of file diff --git a/Kernel/ACPI/ACPIParser.cpp b/Kernel/ACPI/ACPIParser.cpp new file mode 100644 index 0000000000..20f69d4e34 --- /dev/null +++ b/Kernel/ACPI/ACPIParser.cpp @@ -0,0 +1,84 @@ +#include <Kernel/ACPI/ACPIParser.h> + +static ACPIParser* s_acpi_parser; + +ACPIParser& ACPIParser::the() +{ + ASSERT(s_acpi_parser != nullptr); + return *s_acpi_parser; +} + +void ACPIParser::initialize_limited() +{ + if (!ACPIParser::is_initialized()) { + s_acpi_parser = new ACPIParser(false); + } +} + +bool ACPIParser::is_initialized() +{ + return (s_acpi_parser != nullptr); +} + +ACPIParser::ACPIParser(bool usable) +{ + if (usable) { + kprintf("ACPI: Setting up a functional parser\n"); + } else { + kprintf("ACPI: Limited Initialization. Vital functions are disabled by a request\n"); + } + s_acpi_parser = this; +} + +ACPI_RAW::SDTHeader* ACPIParser::find_table(const char*) +{ + kprintf("ACPI: Requested to search for a table, Abort!\n"); + return nullptr; +} + +void ACPIParser::mmap(VirtualAddress, PhysicalAddress, u32) +{ + ASSERT_NOT_REACHED(); +} + +void ACPIParser::mmap_region(Region&, PhysicalAddress) +{ + ASSERT_NOT_REACHED(); +} + +void ACPIParser::do_acpi_reboot() +{ + kprintf("ACPI: Cannot invoke reboot!\n"); + ASSERT_NOT_REACHED(); +} + +void ACPIParser::do_acpi_shutdown() +{ + kprintf("ACPI: Cannot invoke shutdown!\n"); + ASSERT_NOT_REACHED(); +} + +void ACPIParser::enable_aml_interpretation() +{ + kprintf("ACPI: No AML Interpretation Allowed\n"); + ASSERT_NOT_REACHED(); +} +void ACPIParser::enable_aml_interpretation(File&) +{ + kprintf("ACPI: No AML Interpretation Allowed\n"); + ASSERT_NOT_REACHED(); +} +void ACPIParser::enable_aml_interpretation(u8*, u32) +{ + kprintf("ACPI: No AML Interpretation Allowed\n"); + ASSERT_NOT_REACHED(); +} +void ACPIParser::disable_aml_interpretation() +{ + kprintf("ACPI Limited: No AML Interpretation Allowed\n"); + ASSERT_NOT_REACHED(); +} +bool ACPIParser::is_operable() +{ + return false; +}
\ No newline at end of file diff --git a/Kernel/ACPI/ACPIParser.h b/Kernel/ACPI/ACPIParser.h new file mode 100644 index 0000000000..048f3e8137 --- /dev/null +++ b/Kernel/ACPI/ACPIParser.h @@ -0,0 +1,33 @@ +#pragma once + +#include <AK/Types.h> +#include <Kernel/ACPI/Definitions.h> +#include <Kernel/FileSystem/File.h> +#include <Kernel/VM/PhysicalAddress.h> +#include <Kernel/VM/Region.h> +#include <Kernel/VM/VirtualAddress.h> + +class ACPIParser { +public: + static ACPIParser& the(); + + static bool is_initialized(); + static void initialize_limited(); + virtual ACPI_RAW::SDTHeader* find_table(const char* sig); + + virtual void do_acpi_reboot(); + virtual void do_acpi_shutdown(); + + virtual void enable_aml_interpretation(); + virtual void enable_aml_interpretation(File&); + virtual void enable_aml_interpretation(u8*, u32); + virtual void disable_aml_interpretation(); + virtual bool is_operable(); + +protected: + explicit ACPIParser(bool usable); + bool m_operable; + + virtual void mmap(VirtualAddress, PhysicalAddress, u32); + virtual void mmap_region(Region&, PhysicalAddress); +};
\ No newline at end of file diff --git a/Kernel/ACPI/ACPIStaticParser.cpp b/Kernel/ACPI/ACPIStaticParser.cpp new file mode 100644 index 0000000000..60bf9665ec --- /dev/null +++ b/Kernel/ACPI/ACPIStaticParser.cpp @@ -0,0 +1,372 @@ +#include <Kernel/ACPI/ACPIStaticParser.h> +#include <Kernel/IO.h> +#include <Kernel/StdLib.h> +#include <Kernel/VM/MemoryManager.h> + +void ACPIStaticParser::initialize(ACPI_RAW::RSDPDescriptor20& rsdp) +{ + if (!ACPIParser::is_initialized()) { + new ACPIStaticParser(rsdp); + } +} +void ACPIStaticParser::initialize_without_rsdp() +{ + if (!ACPIParser::is_initialized()) { + new ACPIStaticParser(); + } +} + +bool ACPIStaticParser::is_initialized() +{ + return ACPIParser::is_initialized(); +} + +void ACPIStaticParser::locate_static_data() +{ + locate_main_system_description_table(); + initialize_main_system_description_table(); + init_fadt(); + locate_all_aml_tables(); +} + +ACPI_RAW::SDTHeader* ACPIStaticParser::find_table(const char* sig) +{ +#ifdef ACPI_DEBUG + dbgprintf("ACPI: Calling Find Table method!\n"); +#endif + for (auto* physical_sdt_ptr : m_main_sdt->get_sdt_pointers()) { + auto region = MM.allocate_kernel_region((PAGE_SIZE * 2), "ACPI Static Parser Tables Finding", Region::Access::Read); + mmap_region(*region, PhysicalAddress((u32)physical_sdt_ptr)); + ACPI_RAW::SDTHeader* sdt = (ACPI_RAW::SDTHeader*)(region->vaddr().get() + ((u32)physical_sdt_ptr & (~PAGE_MASK))); +#ifdef ACPI_DEBUG + dbgprintf("ACPI: Examining Table @ P 0x%x\n", physical_sdt_ptr); +#endif + if (!strncmp(sdt->sig, sig, 4)) { +#ifdef ACPI_DEBUG + dbgprintf("ACPI: Found Table @ P 0x%x\n", physical_sdt_ptr); +#endif + return physical_sdt_ptr; + } + } + return nullptr; +} + +ACPI_RAW::SDTHeader& ACPIStaticParser::find_fadt() +{ + kprintf("ACPI: Searching for the Fixed ACPI Data Table\n"); + for (auto* physical_sdt_ptr : m_main_sdt->get_sdt_pointers()) { + auto region = MM.allocate_kernel_region((PAGE_SIZE * 2), "ACPI Static Parser AML Tables Finding", Region::Access::Read); + mmap_region(*region, PhysicalAddress((u32)physical_sdt_ptr & PAGE_MASK)); + ACPI_RAW::SDTHeader* sdt = (ACPI_RAW::SDTHeader*)(region->vaddr().get() + ((u32)physical_sdt_ptr & (~PAGE_MASK))); +#ifdef ACPI_DEBUG + dbgprintf("ACPI: Examining Table @ P 0x%x\n", physical_sdt_ptr); +#endif + if (!strncmp(sdt->sig, "FACP", 4)) { + kprintf("ACPI: Found FADT Table @ P 0x%x, registering\n", physical_sdt_ptr); + return *physical_sdt_ptr; + } + } + ASSERT_NOT_REACHED(); // If we reached this point, there's something very incorrect with the system! +} + +void ACPIStaticParser::init_fadt() +{ + kprintf("ACPI: Initializing Fixed ACPI data\n"); + ACPI_RAW::SDTHeader& physical_fadt = find_fadt(); + + auto checkup_region = MM.allocate_kernel_region((PAGE_SIZE * 2), "ACPI Static Parser", Region::Access::Read); +#ifdef ACPI_DEBUG + dbgprintf("ACPI: Checking FADT Length to choose the correct mapping size\n"); +#endif + mmap_region(*checkup_region, PhysicalAddress((u32)(&physical_fadt) & PAGE_MASK)); + + ACPI_RAW::SDTHeader* sdt = (ACPI_RAW::SDTHeader*)(checkup_region->vaddr().get() + ((u32)(&physical_fadt) & (~PAGE_MASK))); +#ifdef ACPI_DEBUG + dbgprintf("ACPI: FADT @ V 0x%x, P 0x%x\n", sdt, &physical_fadt); +#endif + u32 length = sdt->length; + kprintf("ACPI: Fixed ACPI data, Revision %u\n", sdt->revision); + + auto fadt_region = MM.allocate_kernel_region(PAGE_ROUND_UP(length) + PAGE_SIZE, "ACPI Static Parser", Region::Access::Read); + mmap_region(*fadt_region, PhysicalAddress((u32)(&physical_fadt) & PAGE_MASK)); + m_fadt = OwnPtr<ACPI::FixedACPIData>(new ACPI::FixedACPIData(*((ACPI_RAW::FADT*)(fadt_region->vaddr().get() + ((u32)(&physical_fadt) & (~PAGE_MASK)))))); +#ifdef ACPI_DEBUG + dbgprintf("ACPI: Finished to initialize Fixed ACPI data\n"); +#endif +} + +void ACPIStaticParser::do_acpi_reboot() +{ + // FIXME: Determine if we need to do MMIO/PCI/IO access to reboot, according to ACPI spec 6.2, Section 4.8.3.6 +#ifdef ACPI_DEBUG + dbgprintf("ACPI: Rebooting, Probing FADT (P @ 0x%x)\n", m_fadt.ptr()); +#endif + if (m_fadt->m_revision >= 2) { + kprintf("ACPI: Reboot, Sending value 0%x to Port 0x%x\n", m_fadt->m_reset_value, m_fadt->m_reset_reg.address); + IO::out8(m_fadt->m_reset_reg.address, m_fadt->m_reset_value); + } else { + kprintf("ACPI: Reboot, Not supported!\n"); + } + + ASSERT_NOT_REACHED(); /// If rebooting didn't work, halt. +} + +void ACPIStaticParser::do_acpi_shutdown() +{ + kprintf("ACPI: Shutdown is not supported with the current configuration, Abort!\n"); + ASSERT_NOT_REACHED(); +} + +void ACPIStaticParser::initialize_main_system_description_table() +{ + auto checkup_region = MM.allocate_kernel_region((PAGE_SIZE * 2), "ACPI Static Parser Copying Method", Region::Access::Read); +#ifdef ACPI_DEBUG + dbgprintf("ACPI: Checking Main SDT Length to choose the correct mapping size"); +#endif + mmap_region(*checkup_region, PhysicalAddress((u32)m_main_system_description_table & PAGE_MASK)); + + auto* sdt = (ACPI_RAW::SDTHeader*)(checkup_region->vaddr().get() + ((u32)m_main_system_description_table & (~PAGE_MASK))); + u32 length = sdt->length; + u8 revision = sdt->revision; + + auto main_sdt_region = MM.allocate_kernel_region(PAGE_ROUND_UP(length) + PAGE_SIZE, "ACPI Static Parser Copying Method", Region::Access::Read); + mmap_region(*main_sdt_region, PhysicalAddress((u32)m_main_system_description_table & PAGE_MASK)); + + Vector<ACPI_RAW::SDTHeader*> sdt_pointers; + if (m_xsdt_supported) { + ACPI_RAW::XSDT* xsdt = (ACPI_RAW::XSDT*)(main_sdt_region->vaddr().get() + ((u32)m_main_system_description_table & (~PAGE_MASK))); + kprintf("ACPI: Using XSDT, Enumerating tables @ P 0x%x\n", m_main_system_description_table); + kprintf("ACPI: XSDT Revision %d, Total length - %u\n", revision, length); + for (u32 i = 0; i < ((xsdt->h.length - sizeof(ACPI_RAW::SDTHeader)) / sizeof(u64)); i++) { +#ifdef ACPI_DEBUG + dbgprintf("ACPI: Found new table, @ P 0x%x\n", xsdt->table_ptrs[i]); +#endif + sdt_pointers.append((ACPI_RAW::SDTHeader*)xsdt->table_ptrs[i]); + } + } else { + ACPI_RAW::RSDT* rsdt = (ACPI_RAW::RSDT*)(main_sdt_region->vaddr().get() + ((u32)m_main_system_description_table & (~PAGE_MASK))); + kprintf("ACPI: Using RSDT, Enumerating tables @ P 0x%x\n", m_main_system_description_table); + kprintf("ACPI: RSDT Revision %d, Total length - %u\n", revision, length); + for (u32 i = 0; i < ((rsdt->h.length - sizeof(ACPI_RAW::SDTHeader)) / sizeof(u32)); i++) { +#ifdef ACPI_DEBUG + dbgprintf("ACPI: Found new table, @ P 0x%x\n", rsdt->table_ptrs[i]); +#endif + sdt_pointers.append((ACPI_RAW::SDTHeader*)rsdt->table_ptrs[i]); + } + } + m_main_sdt = OwnPtr<ACPI::MainSystemDescriptionTable>(new ACPI::MainSystemDescriptionTable(move(sdt_pointers))); +} + +void ACPIStaticParser::locate_main_system_description_table() +{ + if (m_rsdp->base.revision == 0) { + m_xsdt_supported = false; + } else if (m_rsdp->base.revision >= 2) { + if (m_rsdp->xsdt_ptr != (u64) nullptr) { + m_xsdt_supported = true; + } else { + m_xsdt_supported = false; + } + } + if (!m_xsdt_supported) { + m_main_system_description_table = (ACPI_RAW::SDTHeader*)m_rsdp->base.rsdt_ptr; + } else { + m_main_system_description_table = (ACPI_RAW::SDTHeader*)m_rsdp->xsdt_ptr; + } +} + +void ACPIStaticParser::locate_all_aml_tables() +{ + // Note: According to the ACPI spec, DSDT pointer may be found in the FADT table. + // All other continuation of the DSDT can be found as pointers in the RSDT/XSDT. + + kprintf("ACPI: Searching for AML Tables\n"); + m_aml_tables_ptrs.append(m_fadt->get_dsdt()); + for (auto* sdt_ptr : m_main_sdt->get_sdt_pointers()) { + auto region = MM.allocate_kernel_region((PAGE_SIZE * 2), "ACPI Static Parser AML Tables Finding", Region::Access::Read); + mmap_region(*region, PhysicalAddress((u32)sdt_ptr)); + auto* sdt = (ACPI_RAW::SDTHeader*)(region->vaddr().get() + ((u32)sdt_ptr & (~PAGE_MASK))); +#ifdef ACPI_DEBUG + dbgprintf("ACPI: Examining Table @ P 0x%x\n", sdt_ptr); +#endif + if (!strncmp(sdt->sig, "SSDT", 4)) { + kprintf("ACPI: Found AML Table @ P 0x%x, registering\n", sdt_ptr); + m_aml_tables_ptrs.append(sdt); + } + } +} + +ACPIStaticParser::ACPIStaticParser() + : ACPIParser(true) + , m_rsdp(nullptr) + , m_main_sdt(nullptr) + , m_fadt(nullptr) +{ + m_rsdp = search_rsdp(); + if (m_rsdp != nullptr) { + kprintf("ACPI: Using RSDP @ P 0x%x\n", m_rsdp); + m_operable = true; + locate_static_data(); + } else { + m_operable = false; + kprintf("ACPI: Disabled, due to RSDP being absent\n"); + } +} + +ACPI_RAW::RSDPDescriptor20* ACPIStaticParser::search_rsdp() +{ + auto region = MM.allocate_kernel_region(PAGE_SIZE, "ACPI Static Parser RSDP Finding", Region::Access::Read); + mmap_region(*region, PhysicalAddress(0)); + u16 ebda_seg = (u16) * ((uint16_t*)((region->vaddr().get() & PAGE_MASK) + 0x40e)); + kprintf("ACPI: Probing EBDA, Segment 0x%x\n", ebda_seg); + + // FIXME: Ensure that we always have identity mapping (identity paging) here! Don't rely on existing mapping... + for (char* rsdp_str = (char*)(PhysicalAddress(ebda_seg << 4).as_ptr()); rsdp_str < (char*)((ebda_seg << 4) + 1024); rsdp_str += 16) { +#ifdef ACPI_DEBUG + dbgprintf("ACPI: Looking for RSDP in EBDA @ Px%x\n", rsdp_str); +#endif + if (!strncmp("RSD PTR ", rsdp_str, strlen("RSD PTR "))) + return (ACPI_RAW::RSDPDescriptor20*)rsdp_str; + } + + // FIXME: Ensure that we always have identity mapping (identity paging) here! Don't rely on existing mapping... + for (char* rsdp_str = (char*)(PhysicalAddress(0xE0000).as_ptr()); rsdp_str < (char*)0xFFFFF; rsdp_str += 16) { +#ifdef ACPI_DEBUG + dbgprintf("ACPI: Looking for RSDP in EBDA @ Px%x\n", rsdp_str); +#endif + if (!strncmp("RSD PTR ", rsdp_str, strlen("RSD PTR "))) + return (ACPI_RAW::RSDPDescriptor20*)rsdp_str; + } + return nullptr; +} + +void ACPIStaticParser::mmap(VirtualAddress vaddr, PhysicalAddress paddr, u32 length) +{ + unsigned i = 0; + while (length >= PAGE_SIZE) { + MM.map_for_kernel(VirtualAddress(vaddr.offset(i * PAGE_SIZE).get()), PhysicalAddress(paddr.offset(i * PAGE_SIZE).get())); +#ifdef ACPI_DEBUG + dbgprintf("ACPI: map - V 0x%x -> P 0x%x\n", vaddr.offset(i * PAGE_SIZE).get(), paddr.offset(i * PAGE_SIZE).get()); +#endif + length -= PAGE_SIZE; + i++; + } + if (length > 0) { + MM.map_for_kernel(vaddr.offset(i * PAGE_SIZE), paddr.offset(i * PAGE_SIZE), true); + } +#ifdef ACPI_DEBUG + dbgprintf("ACPI: Finished mapping\n"); +#endif +} + +void ACPIStaticParser::mmap_region(Region& region, PhysicalAddress paddr) +{ +#ifdef ACPI_DEBUG + dbgprintf("ACPI: Mapping region, size - %u\n", region.size()); +#endif + mmap(region.vaddr(), paddr, region.size()); +} + +ACPIStaticParser::ACPIStaticParser(ACPI_RAW::RSDPDescriptor20& rsdp) + : ACPIParser(true) + , m_rsdp(&rsdp) + , m_main_sdt(nullptr) + , m_fadt(nullptr) +{ + kprintf("ACPI: Using RSDP @ Px%x\n", &rsdp); + m_operable = true; + locate_static_data(); +} + +ACPI::MainSystemDescriptionTable::MainSystemDescriptionTable(Vector<ACPI_RAW::SDTHeader*>&& sdt_pointers) +{ + for (auto* sdt_ptr : sdt_pointers) { +#ifdef ACPI_DEBUG + dbgprintf("ACPI: Register new table in Main SDT, @ P 0x%x\n", sdt_ptr); +#endif + m_sdt_pointers.append(sdt_ptr); + } +} +Vector<ACPI_RAW::SDTHeader*>& ACPI::MainSystemDescriptionTable::get_sdt_pointers() +{ + return m_sdt_pointers; +} + +ACPI::FixedACPIData::FixedACPIData(ACPI_RAW::FADT& fadt) +{ + m_dsdt_ptr = fadt.dsdt_ptr; +#ifdef ACPI_DEBUG + dbgprintf("ACPI: DSDT pointer @ P 0x%x\n", m_dsdt_ptr); +#endif + m_revision = fadt.h.revision; + m_x_dsdt_ptr = fadt.x_dsdt; + m_preferred_pm_profile = fadt.preferred_pm_profile; + m_sci_int = fadt.sci_int; + m_smi_cmd = fadt.smi_cmd; + m_acpi_enable_value = fadt.acpi_enable_value; + m_acpi_disable_value = fadt.acpi_disable_value; + m_s4bios_req = fadt.s4bios_req; + m_pstate_cnt = fadt.pstate_cnt; + + m_PM1a_EVT_BLK = fadt.PM1a_EVT_BLK; + m_PM1b_EVT_BLK = fadt.PM1b_EVT_BLK; + m_PM1a_CNT_BLK = fadt.PM1a_CNT_BLK; + m_PM1b_CNT_BLK = fadt.PM1b_CNT_BLK; + m_PM2_CNT_BLK = fadt.PM2_CNT_BLK; + m_PM_TMR_BLK = fadt.PM_TMR_BLK; + m_GPE0_BLK = fadt.GPE0_BLK; + m_GPE1_BLK = fadt.GPE1_BLK; + m_PM1_EVT_LEN = fadt.PM1_EVT_LEN; + m_PM1_CNT_LEN = fadt.PM1_CNT_LEN; + m_PM2_CNT_LEN = fadt.PM2_CNT_LEN; + m_PM_TMR_LEN = fadt.PM_TMR_LEN; + m_GPE0_BLK_LEN = fadt.GPE0_BLK_LEN; + m_GPE1_BLK_LEN = fadt.GPE1_BLK_LEN; + m_GPE1_BASE = fadt.GPE1_BASE; + m_cst_cnt = fadt.cst_cnt; + m_P_LVL2_LAT = fadt.P_LVL2_LAT; + m_P_LVL3_LAT = fadt.P_LVL3_LAT; + m_flush_size = fadt.flush_size; + + m_flush_stride = fadt.flush_stride; + m_duty_offset = fadt.duty_offset; + m_duty_width = fadt.duty_width; + m_day_alrm = fadt.day_alrm; + m_mon_alrm = fadt.mon_alrm; + m_century = fadt.century; + + m_ia_pc_boot_arch_flags = fadt.ia_pc_boot_arch_flags; + m_flags = fadt.flags; + + m_reset_reg = fadt.reset_reg; +#ifdef ACPI_DEBUG + dbgprintf("ACPI: Reset Register @ IO 0x%x\n", m_reset_reg.address); + dbgprintf("ACPI: Reset Register Address space %x\n", fadt.reset_reg.address_space); +#endif + m_reset_value = fadt.reset_value; +#ifdef ACPI_DEBUG + dbgprintf("ACPI: Reset Register value @ P 0x%x\n", m_reset_value); +#endif + m_x_pm1a_evt_blk = fadt.x_pm1a_evt_blk; + m_x_pm1b_evt_blk = fadt.x_pm1b_evt_blk; + m_x_pm1a_cnt_blk = fadt.x_pm1a_cnt_blk; + m_x_pm1b_cnt_blk = fadt.x_pm1b_cnt_blk; + m_x_pm2_cnt_blk = fadt.x_pm2_cnt_blk; + m_x_pm_tmr_blk = fadt.x_pm_tmr_blk; + m_x_gpe0_blk = fadt.x_gpe0_blk; + m_x_gpe1_blk = fadt.x_gpe1_blk; + m_sleep_control = fadt.sleep_control; + m_sleep_status = fadt.sleep_status; + + m_hypervisor_vendor_identity = fadt.hypervisor_vendor_identity; +} + +ACPI_RAW::SDTHeader* ACPI::FixedACPIData::get_dsdt() +{ + if (m_x_dsdt_ptr != (u32) nullptr) + return (ACPI_RAW::SDTHeader*)m_x_dsdt_ptr; + else { + ASSERT((ACPI_RAW::SDTHeader*)m_dsdt_ptr != nullptr); + return (ACPI_RAW::SDTHeader*)m_dsdt_ptr; + } +} diff --git a/Kernel/ACPI/ACPIStaticParser.h b/Kernel/ACPI/ACPIStaticParser.h new file mode 100644 index 0000000000..2970372280 --- /dev/null +++ b/Kernel/ACPI/ACPIStaticParser.h @@ -0,0 +1,42 @@ +#pragma once + +#include <ACPI/ACPIParser.h> +#include <AK/OwnPtr.h> + +class ACPIStaticParser : ACPIParser { +public: + static void initialize(ACPI_RAW::RSDPDescriptor20& rsdp); + static void initialize_without_rsdp(); + static bool is_initialized(); + + virtual ACPI_RAW::SDTHeader* find_table(const char* sig) override; + virtual void do_acpi_reboot() override; + virtual void do_acpi_shutdown() override; + virtual bool is_operable() override { return m_operable; } + +protected: + ACPIStaticParser(); + explicit ACPIStaticParser(ACPI_RAW::RSDPDescriptor20&); + + virtual void mmap(VirtualAddress preferred_vaddr, PhysicalAddress paddr, u32) override; + virtual void mmap_region(Region& region, PhysicalAddress paddr) override; + +private: + void locate_static_data(); + void locate_all_aml_tables(); + void locate_main_system_description_table(); + void initialize_main_system_description_table(); + ACPI_RAW::SDTHeader& find_fadt(); + void init_fadt(); + ACPI_RAW::RSDPDescriptor20* search_rsdp(); + + // Early pointers that are needed really for initializtion only... + ACPI_RAW::RSDPDescriptor20* m_rsdp; + ACPI_RAW::SDTHeader* m_main_system_description_table; + + OwnPtr<ACPI::MainSystemDescriptionTable> m_main_sdt; + OwnPtr<ACPI::FixedACPIData> m_fadt; + + Vector<ACPI_RAW::SDTHeader*> m_aml_tables_ptrs; + bool m_xsdt_supported; +};
\ No newline at end of file diff --git a/Kernel/ACPI/Definitions.h b/Kernel/ACPI/Definitions.h new file mode 100644 index 0000000000..483ea7d8d2 --- /dev/null +++ b/Kernel/ACPI/Definitions.h @@ -0,0 +1,262 @@ +#pragma once + +#include <AK/RefCounted.h> +#include <AK/Types.h> +#include <AK/Vector.h> + +namespace ACPI_RAW { + +struct RSDPDescriptor { + char sig[8]; + u8 checksum; + char oem_id[6]; + u8 revision; + u32 rsdt_ptr; +} __attribute__((__packed__)); + +struct RSDPDescriptor20 { + RSDPDescriptor base; + u32 length; + u64 xsdt_ptr; + u8 ext_checksum; + u8 reserved[3]; +} __attribute__((__packed__)); + +struct SDTHeader { + char sig[4]; + u32 length; + u8 revision; + u8 checksum; + char oem_id[6]; + char oem_table_id[8]; + u32 oem_revision; + u32 creator_id; + u32 creator_revision; +} __attribute__((__packed__)); + +struct RSDT { + SDTHeader h; + u32 table_ptrs[1]; +} __attribute__((__packed__)); + +struct XSDT { + SDTHeader h; + u64 table_ptrs[1]; +} __attribute__((__packed__)); + +struct GenericAddressStructure { + u8 address_space; + u8 bit_width; + u8 bit_offset; + u8 access_size; + u64 address; +} __attribute__((__packed__)); + +struct FADT { + SDTHeader h; + u32 firmware_ctrl; + u32 dsdt_ptr; + u8 reserved; + u8 preferred_pm_profile; + u16 sci_int; + u32 smi_cmd; + u8 acpi_enable_value; + u8 acpi_disable_value; + u8 s4bios_req; + u8 pstate_cnt; + u32 PM1a_EVT_BLK; + u32 PM1b_EVT_BLK; + u32 PM1a_CNT_BLK; + u32 PM1b_CNT_BLK; + u32 PM2_CNT_BLK; + u32 PM_TMR_BLK; + u32 GPE0_BLK; + u32 GPE1_BLK; + u8 PM1_EVT_LEN; + u8 PM1_CNT_LEN; + u8 PM2_CNT_LEN; + u8 PM_TMR_LEN; + u8 GPE0_BLK_LEN; + u8 GPE1_BLK_LEN; + u8 GPE1_BASE; + u8 cst_cnt; + u16 P_LVL2_LAT; + u16 P_LVL3_LAT; + u16 flush_size; + u16 flush_stride; + u8 duty_offset; + u8 duty_width; + u8 day_alrm; + u8 mon_alrm; + u8 century; + u16 ia_pc_boot_arch_flags; + u8 reserved2; + u32 flags; + GenericAddressStructure reset_reg; + u8 reset_value; + u16 arm_boot_arch; + u8 fadt_minor_version; + u64 x_firmware_ctrl; + u64 x_dsdt; + GenericAddressStructure x_pm1a_evt_blk; + GenericAddressStructure x_pm1b_evt_blk; + GenericAddressStructure x_pm1a_cnt_blk; + GenericAddressStructure x_pm1b_cnt_blk; + GenericAddressStructure x_pm2_cnt_blk; + GenericAddressStructure x_pm_tmr_blk; + GenericAddressStructure x_gpe0_blk; + GenericAddressStructure x_gpe1_blk; + GenericAddressStructure sleep_control; + GenericAddressStructure sleep_status; + u64 hypervisor_vendor_identity; + +} __attribute__((__packed__)); + +struct MADT : public SDTHeader { +}; + +struct DSDT : public SDTHeader { +}; + +struct PCI_MMIO_Descriptor { + u64 base_addr; + u16 seg_group_number; + u8 start_pci_bus; + u8 end_pci_bus; + u32 reserved; +} __attribute__((__packed__)); + +struct MCFG { + SDTHeader header; + u64 reserved; + PCI_MMIO_Descriptor descriptors[]; +} __attribute__((__packed__)); +} + +class ACPIStaticParser; + +namespace ACPI { + +class SDT : public RefCounted<SDT> { +}; + +struct GenericAddressStructure { + u8 address_space; + u8 bit_width; + u8 bit_offset; + u8 access_size; + u64 address; + GenericAddressStructure& operator=(const GenericAddressStructure& other) + { + this->address_space = other.address_space; + this->bit_width = other.bit_width; + this->bit_offset = other.bit_offset; + this->access_size = other.access_size; + this->address = (u32)other.address; + return *this; + } + GenericAddressStructure& operator=(const ACPI_RAW::GenericAddressStructure& other) + { + this->address_space = other.address_space; + this->bit_width = other.bit_width; + this->bit_offset = other.bit_offset; + this->access_size = other.access_size; + this->address = (u32)other.address; + return *this; + } +}; + +class FixedACPIData; +} + +class ACPI::FixedACPIData : public ACPI::SDT { + friend ACPIStaticParser; + +public: + explicit FixedACPIData(ACPI_RAW::FADT&); + ACPI_RAW::SDTHeader* get_dsdt(); + +private: + u8 m_revision; + u32 m_dsdt_ptr; + u64 m_x_dsdt_ptr; + u8 m_preferred_pm_profile; + u16 m_sci_int; + u32 m_smi_cmd; + u8 m_acpi_enable_value; + u8 m_acpi_disable_value; + u8 m_s4bios_req; + u8 m_pstate_cnt; + u32 m_PM1a_EVT_BLK; + u32 m_PM1b_EVT_BLK; + u32 m_PM1a_CNT_BLK; + u32 m_PM1b_CNT_BLK; + u32 m_PM2_CNT_BLK; + u32 m_PM_TMR_BLK; + u32 m_GPE0_BLK; + u32 m_GPE1_BLK; + u8 m_PM1_EVT_LEN; + u8 m_PM1_CNT_LEN; + u8 m_PM2_CNT_LEN; + u8 m_PM_TMR_LEN; + u8 m_GPE0_BLK_LEN; + u8 m_GPE1_BLK_LEN; + u8 m_GPE1_BASE; + u8 m_cst_cnt; + u16 m_P_LVL2_LAT; + u16 m_P_LVL3_LAT; + u16 m_flush_size; + u16 m_flush_stride; + u8 m_duty_offset; + u8 m_duty_width; + u8 m_day_alrm; + u8 m_mon_alrm; + u8 m_century; + u16 m_ia_pc_boot_arch_flags; + u32 m_flags; + ACPI::GenericAddressStructure m_reset_reg; + u8 m_reset_value; + ACPI::GenericAddressStructure m_x_pm1a_evt_blk; + ACPI::GenericAddressStructure m_x_pm1b_evt_blk; + ACPI::GenericAddressStructure m_x_pm1a_cnt_blk; + ACPI::GenericAddressStructure m_x_pm1b_cnt_blk; + ACPI::GenericAddressStructure m_x_pm2_cnt_blk; + ACPI::GenericAddressStructure m_x_pm_tmr_blk; + ACPI::GenericAddressStructure m_x_gpe0_blk; + ACPI::GenericAddressStructure m_x_gpe1_blk; + ACPI::GenericAddressStructure m_sleep_control; + ACPI::GenericAddressStructure m_sleep_status; + u64 m_hypervisor_vendor_identity; +}; + +namespace ACPI { + +class MainSystemDescriptionTable : public SDT { +public: + explicit MainSystemDescriptionTable(Vector<ACPI_RAW::SDTHeader*>&& sdt_pointers); + Vector<ACPI_RAW::SDTHeader*>& get_sdt_pointers(); + +private: + Vector<ACPI_RAW::SDTHeader*> m_sdt_pointers; +}; + +class MCFG : public SDT { +public: + MCFG(ACPI_RAW::MCFG&); +}; + +class FACS : public SDT { + +public: +private: + u32 hardware_sig; + u32 waking_vector; + u32 global_lock; + u32 flags; + u64 x_waking_vector; + u32 ospm_flags; +}; + +class MADT : public SDT { +}; +} diff --git a/Kernel/StdLib.h b/Kernel/StdLib.h index 2eaf9797a1..35b10a6e30 100644 --- a/Kernel/StdLib.h +++ b/Kernel/StdLib.h @@ -9,6 +9,7 @@ static_assert(sizeof(size_t) == 4); void* memcpy(void*, const void*, size_t); char* strcpy(char*, const char*); char* strncpy(char*, const char*, size_t); +int strncmp(const char* s1, const char* s2, size_t n); int strcmp(char const*, const char*); size_t strlen(const char*); size_t strnlen(const char*, size_t); |