Kernel/ACPI: Make most of StaticParsing methods to be platform-agnostic
Most of the ACPI static parsing methods (methods that can be called without initializing a full AML parser) are not tied to any specific platform or CPU architecture. The only method that is platform-specific is the one that finds the RSDP structure. Thus, each CPU architecture/platform needs to implement it. This means that now aarch64 can implement its own method to find the ACPI RSDP structure, which would be hooked into the rest of the ACPI code elegantly, but for now I just added a FIXME and that method returns empty value of Optional<PhysicalAddress>.
This commit is contained in:
parent
be16a91aec
commit
428afca32b
Notes:
sideshowbarker
2024-07-17 02:21:14 +09:00
Author: https://github.com/supercomputer7 Commit: https://github.com/SerenityOS/serenity/commit/428afca32b Pull-request: https://github.com/SerenityOS/serenity/pull/19336 Reviewed-by: https://github.com/gmta ✅ Reviewed-by: https://github.com/kleinesfilmroellchen
11 changed files with 211 additions and 133 deletions
17
Kernel/Arch/aarch64/Firmware/ACPI/StaticParsing.cpp
Normal file
17
Kernel/Arch/aarch64/Firmware/ACPI/StaticParsing.cpp
Normal file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/Firmware/ACPI/StaticParsing.h>
|
||||
|
||||
namespace Kernel::ACPI::StaticParsing {
|
||||
|
||||
ErrorOr<Optional<PhysicalAddress>> find_rsdp_in_platform_specific_memory_locations()
|
||||
{
|
||||
// FIXME: Implement finding RSDP for aarch64.
|
||||
return Optional<PhysicalAddress> {};
|
||||
}
|
||||
|
||||
}
|
57
Kernel/Arch/x86_64/Firmware/ACPI/StaticParsing.cpp
Normal file
57
Kernel/Arch/x86_64/Firmware/ACPI/StaticParsing.cpp
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/Firmware/ACPI/StaticParsing.h>
|
||||
#include <Kernel/Firmware/BIOS.h>
|
||||
#include <Kernel/Memory/MemoryManager.h>
|
||||
|
||||
namespace Kernel::ACPI::StaticParsing {
|
||||
|
||||
// https://uefi.org/specs/ACPI/6.4/05_ACPI_Software_Programming_Model/ACPI_Software_Programming_Model.html#finding-the-rsdp-on-ia-pc-systems
|
||||
ErrorOr<Optional<PhysicalAddress>> find_rsdp_in_platform_specific_memory_locations()
|
||||
{
|
||||
constexpr auto signature = "RSD PTR "sv;
|
||||
auto ebda_or_error = map_ebda();
|
||||
if (!ebda_or_error.is_error()) {
|
||||
auto rsdp = ebda_or_error.value().find_chunk_starting_with(signature, 16);
|
||||
if (rsdp.has_value())
|
||||
return rsdp;
|
||||
}
|
||||
auto bios_or_error = map_bios();
|
||||
if (!bios_or_error.is_error()) {
|
||||
auto rsdp = bios_or_error.value().find_chunk_starting_with(signature, 16);
|
||||
if (rsdp.has_value())
|
||||
return rsdp;
|
||||
}
|
||||
|
||||
// On some systems the RSDP may be located in ACPI NVS or reclaimable memory regions
|
||||
Optional<PhysicalAddress> rsdp;
|
||||
MM.for_each_physical_memory_range([&](auto& memory_range) {
|
||||
if (!(memory_range.type == Memory::PhysicalMemoryRangeType::ACPI_NVS || memory_range.type == Memory::PhysicalMemoryRangeType::ACPI_Reclaimable))
|
||||
return IterationDecision::Continue;
|
||||
|
||||
Memory::MappedROM mapping;
|
||||
auto region_size_or_error = Memory::page_round_up(memory_range.length);
|
||||
if (region_size_or_error.is_error())
|
||||
return IterationDecision::Continue;
|
||||
auto region_or_error = MM.allocate_kernel_region(memory_range.start, region_size_or_error.value(), {}, Memory::Region::Access::Read);
|
||||
if (region_or_error.is_error())
|
||||
return IterationDecision::Continue;
|
||||
mapping.region = region_or_error.release_value();
|
||||
mapping.offset = memory_range.start.offset_in_page();
|
||||
mapping.size = memory_range.length;
|
||||
mapping.paddr = memory_range.start;
|
||||
|
||||
rsdp = mapping.find_chunk_starting_with(signature, 16);
|
||||
if (rsdp.has_value())
|
||||
return IterationDecision::Break;
|
||||
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
return rsdp;
|
||||
}
|
||||
|
||||
}
|
|
@ -12,6 +12,7 @@
|
|||
#include <Kernel/Arch/x86_64/Interrupts/IOAPIC.h>
|
||||
#include <Kernel/Arch/x86_64/Interrupts/PIC.h>
|
||||
#include <Kernel/Boot/CommandLine.h>
|
||||
#include <Kernel/Firmware/ACPI/StaticParsing.h>
|
||||
#include <Kernel/Firmware/MultiProcessor/Parser.h>
|
||||
#include <Kernel/Interrupts/InterruptDisabler.h>
|
||||
#include <Kernel/Interrupts/SharedIRQHandler.h>
|
||||
|
@ -118,20 +119,19 @@ NonnullLockRefPtr<IRQController> InterruptManagement::get_responsible_irq_contro
|
|||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT PhysicalAddress InterruptManagement::search_for_madt()
|
||||
UNMAP_AFTER_INIT ErrorOr<Optional<PhysicalAddress>> InterruptManagement::find_madt_physical_address()
|
||||
{
|
||||
dbgln("Early access to ACPI tables for interrupt setup");
|
||||
auto rsdp = ACPI::StaticParsing::find_rsdp();
|
||||
if (!rsdp.has_value())
|
||||
return {};
|
||||
auto apic = ACPI::StaticParsing::find_table(rsdp.value(), "APIC"sv);
|
||||
if (!apic.has_value())
|
||||
return {};
|
||||
return apic.value();
|
||||
auto possible_rsdp_physical_address = TRY(ACPI::StaticParsing::find_rsdp_in_platform_specific_memory_locations());
|
||||
if (!possible_rsdp_physical_address.has_value())
|
||||
return Optional<PhysicalAddress> {};
|
||||
auto possible_apic_physical_address = TRY(ACPI::StaticParsing::find_table(possible_rsdp_physical_address.value(), "APIC"sv));
|
||||
if (!possible_apic_physical_address.has_value())
|
||||
return Optional<PhysicalAddress> {};
|
||||
return possible_apic_physical_address.value();
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT InterruptManagement::InterruptManagement()
|
||||
: m_madt(search_for_madt())
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -151,13 +151,15 @@ UNMAP_AFTER_INIT void InterruptManagement::switch_to_ioapic_mode()
|
|||
dmesgln("Interrupts: Switch to IOAPIC mode");
|
||||
InterruptDisabler disabler;
|
||||
|
||||
if (m_madt.is_null()) {
|
||||
m_madt_physical_address = MUST(find_madt_physical_address());
|
||||
|
||||
if (!m_madt_physical_address.has_value()) {
|
||||
dbgln("Interrupts: ACPI MADT is not available, reverting to PIC mode");
|
||||
switch_to_pic_mode();
|
||||
return;
|
||||
}
|
||||
|
||||
dbgln("Interrupts: MADT @ P {}", m_madt.as_ptr());
|
||||
dbgln("Interrupts: MADT @ P {}", m_madt_physical_address.value().as_ptr());
|
||||
locate_apic_data();
|
||||
if (m_interrupt_controllers.size() == 1) {
|
||||
if (get_interrupt_controller(0).type() == IRQControllerType::i8259) {
|
||||
|
@ -187,8 +189,8 @@ UNMAP_AFTER_INIT void InterruptManagement::switch_to_ioapic_mode()
|
|||
|
||||
UNMAP_AFTER_INIT void InterruptManagement::locate_apic_data()
|
||||
{
|
||||
VERIFY(!m_madt.is_null());
|
||||
auto madt = Memory::map_typed<ACPI::Structures::MADT>(m_madt).release_value_but_fixme_should_propagate_errors();
|
||||
VERIFY(m_madt_physical_address.has_value());
|
||||
auto madt = Memory::map_typed<ACPI::Structures::MADT>(m_madt_physical_address.value()).release_value_but_fixme_should_propagate_errors();
|
||||
|
||||
if (madt->flags & PCAT_COMPAT_FLAG)
|
||||
m_interrupt_controllers.append(adopt_lock_ref(*new PIC()));
|
||||
|
|
|
@ -48,8 +48,8 @@ public:
|
|||
static u8 acquire_mapped_interrupt_number(u8 original_irq);
|
||||
static u8 acquire_irq_number(u8 mapped_interrupt_vector);
|
||||
|
||||
virtual void switch_to_pic_mode();
|
||||
virtual void switch_to_ioapic_mode();
|
||||
void switch_to_pic_mode();
|
||||
void switch_to_ioapic_mode();
|
||||
|
||||
NonnullLockRefPtr<IRQController> get_responsible_irq_controller(u8 interrupt_vector);
|
||||
NonnullLockRefPtr<IRQController> get_responsible_irq_controller(IRQControllerType controller_type, u8 interrupt_vector);
|
||||
|
@ -67,12 +67,12 @@ protected:
|
|||
|
||||
private:
|
||||
InterruptManagement();
|
||||
PhysicalAddress search_for_madt();
|
||||
ErrorOr<Optional<PhysicalAddress>> find_madt_physical_address();
|
||||
void locate_apic_data();
|
||||
Vector<NonnullLockRefPtr<IRQController>> m_interrupt_controllers;
|
||||
Vector<ISAInterruptOverrideMetadata> m_isa_interrupt_overrides;
|
||||
Vector<PCIInterruptOverrideMetadata> m_pci_interrupt_overrides;
|
||||
PhysicalAddress m_madt;
|
||||
Optional<PhysicalAddress> m_madt_physical_address;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
#include <Kernel/Arch/x86_64/Time/APICTimer.h>
|
||||
#include <Kernel/Debug.h>
|
||||
#include <Kernel/Firmware/ACPI/Parser.h>
|
||||
#include <Kernel/Firmware/ACPI/StaticParsing.h>
|
||||
#include <Kernel/Interrupts/SpuriousInterruptHandler.h>
|
||||
#include <Kernel/Library/Panic.h>
|
||||
#include <Kernel/Memory/AnonymousVMObject.h>
|
||||
|
@ -261,19 +262,30 @@ UNMAP_AFTER_INIT bool APIC::init_bsp()
|
|||
m_apic_base = region_or_error.release_value();
|
||||
}
|
||||
|
||||
auto rsdp = ACPI::StaticParsing::find_rsdp();
|
||||
if (!rsdp.has_value()) {
|
||||
auto possible_rsdp_physical_address_or_error = ACPI::StaticParsing::find_rsdp_in_platform_specific_memory_locations();
|
||||
if (possible_rsdp_physical_address_or_error.is_error()) {
|
||||
dbgln("APIC: Failed to map RSDP");
|
||||
return false;
|
||||
}
|
||||
auto possible_rsdp_physical_address = possible_rsdp_physical_address_or_error.release_value();
|
||||
if (!possible_rsdp_physical_address.has_value()) {
|
||||
dbgln("APIC: RSDP not found");
|
||||
return false;
|
||||
}
|
||||
auto madt_address = ACPI::StaticParsing::find_table(rsdp.value(), "APIC"sv);
|
||||
if (!madt_address.has_value()) {
|
||||
|
||||
auto possible_apic_physical_address_or_error = ACPI::StaticParsing::find_table(possible_rsdp_physical_address.value(), "APIC"sv);
|
||||
if (possible_apic_physical_address_or_error.is_error()) {
|
||||
dbgln("APIC: Failed to map RSDT/XSDT");
|
||||
return false;
|
||||
}
|
||||
auto possible_apic_physical_address = possible_apic_physical_address_or_error.release_value();
|
||||
if (!possible_apic_physical_address.has_value()) {
|
||||
dbgln("APIC: MADT table not found");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (kernel_command_line().is_smp_enabled()) {
|
||||
auto madt_or_error = Memory::map_typed<ACPI::Structures::MADT>(madt_address.value());
|
||||
auto madt_or_error = Memory::map_typed<ACPI::Structures::MADT>(possible_apic_physical_address.value());
|
||||
if (madt_or_error.is_error()) {
|
||||
dbgln("APIC: Failed to map MADT table");
|
||||
return false;
|
||||
|
|
|
@ -209,6 +209,7 @@ set(KERNEL_SOURCES
|
|||
Firmware/BIOS.cpp
|
||||
Firmware/ACPI/Initialize.cpp
|
||||
Firmware/ACPI/Parser.cpp
|
||||
Firmware/ACPI/StaticParsing.cpp
|
||||
Firmware/MultiProcessor/Parser.cpp
|
||||
Interrupts/GenericInterruptHandler.cpp
|
||||
Interrupts/IRQHandler.cpp
|
||||
|
@ -370,6 +371,8 @@ if ("${SERENITY_ARCH}" STREQUAL "x86_64")
|
|||
Arch/x86_64/DebugOutput.cpp
|
||||
Arch/x86_64/Delay.cpp
|
||||
|
||||
Arch/x86_64/Firmware/ACPI/StaticParsing.cpp
|
||||
|
||||
Arch/x86_64/Hypervisor/BochsDisplayConnector.cpp
|
||||
Arch/x86_64/Hypervisor/VMWareBackdoor.cpp
|
||||
|
||||
|
@ -460,6 +463,8 @@ elseif("${SERENITY_ARCH}" STREQUAL "aarch64")
|
|||
${SOURCES_RUNNING_WITHOUT_MMU}
|
||||
Arch/Processor.cpp
|
||||
|
||||
Arch/aarch64/Firmware/ACPI/StaticParsing.cpp
|
||||
|
||||
Arch/aarch64/boot.S
|
||||
Arch/aarch64/BootPPMParser.cpp
|
||||
Arch/aarch64/CPUID.cpp
|
||||
|
|
|
@ -327,11 +327,4 @@ struct [[gnu::packed]] DSDT {
|
|||
};
|
||||
}
|
||||
|
||||
class Parser;
|
||||
|
||||
namespace StaticParsing {
|
||||
Optional<PhysicalAddress> find_rsdp();
|
||||
Optional<PhysicalAddress> find_table(PhysicalAddress rsdp, StringView signature);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include <Kernel/Boot/CommandLine.h>
|
||||
#include <Kernel/Firmware/ACPI/Parser.h>
|
||||
#include <Kernel/Firmware/ACPI/StaticParsing.h>
|
||||
#include <Kernel/Memory/TypedMapping.h>
|
||||
#include <Kernel/Sections.h>
|
||||
|
||||
|
@ -18,11 +19,11 @@ UNMAP_AFTER_INIT void initialize()
|
|||
if (feature_level == AcpiFeatureLevel::Disabled)
|
||||
return;
|
||||
|
||||
auto rsdp = StaticParsing::find_rsdp();
|
||||
auto rsdp = MUST(StaticParsing::find_rsdp_in_platform_specific_memory_locations());
|
||||
if (!rsdp.has_value())
|
||||
return;
|
||||
|
||||
auto facp = StaticParsing::find_table(rsdp.value(), "FACP"sv);
|
||||
auto facp = MUST(StaticParsing::find_table(rsdp.value(), "FACP"sv));
|
||||
if (!facp.has_value())
|
||||
return;
|
||||
auto facp_table_or_error = Memory::map_typed<Structures::FADT>(facp.value());
|
||||
|
|
|
@ -120,9 +120,6 @@ void Parser::enumerate_static_tables(Function<void(StringView, PhysicalAddress,
|
|||
}
|
||||
}
|
||||
|
||||
static bool match_table_signature(PhysicalAddress table_header, StringView signature);
|
||||
static Optional<PhysicalAddress> search_table_in_xsdt(PhysicalAddress xsdt, StringView signature);
|
||||
static Optional<PhysicalAddress> search_table_in_rsdt(PhysicalAddress rsdt, StringView signature);
|
||||
static bool validate_table(Structures::SDTHeader const&, size_t length);
|
||||
|
||||
UNMAP_AFTER_INIT void Parser::locate_static_data()
|
||||
|
@ -417,103 +414,4 @@ static bool validate_table(Structures::SDTHeader const& v_header, size_t length)
|
|||
return false;
|
||||
}
|
||||
|
||||
// https://uefi.org/specs/ACPI/6.4/05_ACPI_Software_Programming_Model/ACPI_Software_Programming_Model.html#finding-the-rsdp-on-ia-pc-systems
|
||||
UNMAP_AFTER_INIT Optional<PhysicalAddress> StaticParsing::find_rsdp()
|
||||
{
|
||||
constexpr auto signature = "RSD PTR "sv;
|
||||
auto ebda_or_error = map_ebda();
|
||||
if (!ebda_or_error.is_error()) {
|
||||
auto rsdp = ebda_or_error.value().find_chunk_starting_with(signature, 16);
|
||||
if (rsdp.has_value())
|
||||
return rsdp;
|
||||
}
|
||||
auto bios_or_error = map_bios();
|
||||
if (!bios_or_error.is_error()) {
|
||||
auto rsdp = bios_or_error.value().find_chunk_starting_with(signature, 16);
|
||||
if (rsdp.has_value())
|
||||
return rsdp;
|
||||
}
|
||||
|
||||
// On some systems the RSDP may be located in ACPI NVS or reclaimable memory regions
|
||||
Optional<PhysicalAddress> rsdp;
|
||||
MM.for_each_physical_memory_range([&](auto& memory_range) {
|
||||
if (!(memory_range.type == Memory::PhysicalMemoryRangeType::ACPI_NVS || memory_range.type == Memory::PhysicalMemoryRangeType::ACPI_Reclaimable))
|
||||
return IterationDecision::Continue;
|
||||
|
||||
Memory::MappedROM mapping;
|
||||
auto region_size_or_error = Memory::page_round_up(memory_range.length);
|
||||
if (region_size_or_error.is_error())
|
||||
return IterationDecision::Continue;
|
||||
auto region_or_error = MM.allocate_kernel_region(memory_range.start, region_size_or_error.value(), {}, Memory::Region::Access::Read);
|
||||
if (region_or_error.is_error())
|
||||
return IterationDecision::Continue;
|
||||
mapping.region = region_or_error.release_value();
|
||||
mapping.offset = memory_range.start.offset_in_page();
|
||||
mapping.size = memory_range.length;
|
||||
mapping.paddr = memory_range.start;
|
||||
|
||||
rsdp = mapping.find_chunk_starting_with(signature, 16);
|
||||
if (rsdp.has_value())
|
||||
return IterationDecision::Break;
|
||||
|
||||
return IterationDecision::Continue;
|
||||
});
|
||||
return rsdp;
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT Optional<PhysicalAddress> StaticParsing::find_table(PhysicalAddress rsdp_address, StringView signature)
|
||||
{
|
||||
// FIXME: There's no validation of ACPI tables here. Use the checksum to validate the tables.
|
||||
VERIFY(signature.length() == 4);
|
||||
|
||||
auto rsdp = Memory::map_typed<Structures::RSDPDescriptor20>(rsdp_address).release_value_but_fixme_should_propagate_errors();
|
||||
|
||||
if (rsdp->base.revision == 0)
|
||||
return search_table_in_rsdt(PhysicalAddress(rsdp->base.rsdt_ptr), signature);
|
||||
|
||||
if (rsdp->base.revision >= 2) {
|
||||
if (rsdp->xsdt_ptr)
|
||||
return search_table_in_xsdt(PhysicalAddress(rsdp->xsdt_ptr), signature);
|
||||
return search_table_in_rsdt(PhysicalAddress(rsdp->base.rsdt_ptr), signature);
|
||||
}
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT static Optional<PhysicalAddress> search_table_in_xsdt(PhysicalAddress xsdt_address, StringView signature)
|
||||
{
|
||||
// FIXME: There's no validation of ACPI tables here. Use the checksum to validate the tables.
|
||||
VERIFY(signature.length() == 4);
|
||||
|
||||
auto xsdt = Memory::map_typed<Structures::XSDT>(xsdt_address).release_value_but_fixme_should_propagate_errors();
|
||||
|
||||
for (size_t i = 0; i < ((xsdt->h.length - sizeof(Structures::SDTHeader)) / sizeof(u64)); ++i) {
|
||||
if (match_table_signature(PhysicalAddress((PhysicalPtr)xsdt->table_ptrs[i]), signature))
|
||||
return PhysicalAddress((PhysicalPtr)xsdt->table_ptrs[i]);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
static bool match_table_signature(PhysicalAddress table_header, StringView signature)
|
||||
{
|
||||
// FIXME: There's no validation of ACPI tables here. Use the checksum to validate the tables.
|
||||
VERIFY(signature.length() == 4);
|
||||
|
||||
auto table = Memory::map_typed<Structures::RSDT>(table_header).release_value_but_fixme_should_propagate_errors();
|
||||
return !strncmp(table->h.sig, signature.characters_without_null_termination(), 4);
|
||||
}
|
||||
|
||||
UNMAP_AFTER_INIT static Optional<PhysicalAddress> search_table_in_rsdt(PhysicalAddress rsdt_address, StringView signature)
|
||||
{
|
||||
// FIXME: There's no validation of ACPI tables here. Use the checksum to validate the tables.
|
||||
VERIFY(signature.length() == 4);
|
||||
|
||||
auto rsdt = Memory::map_typed<Structures::RSDT>(rsdt_address).release_value_but_fixme_should_propagate_errors();
|
||||
|
||||
for (u32 i = 0; i < ((rsdt->h.length - sizeof(Structures::SDTHeader)) / sizeof(u32)); i++) {
|
||||
if (match_table_signature(PhysicalAddress((PhysicalPtr)rsdt->table_ptrs[i]), signature))
|
||||
return PhysicalAddress((PhysicalPtr)rsdt->table_ptrs[i]);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
}
|
||||
|
|
69
Kernel/Firmware/ACPI/StaticParsing.cpp
Normal file
69
Kernel/Firmware/ACPI/StaticParsing.cpp
Normal file
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#include <Kernel/Firmware/ACPI/Definitions.h>
|
||||
#include <Kernel/Firmware/ACPI/StaticParsing.h>
|
||||
#include <Kernel/Library/StdLib.h>
|
||||
#include <Kernel/Memory/TypedMapping.h>
|
||||
|
||||
namespace Kernel::ACPI::StaticParsing {
|
||||
|
||||
static bool match_table_signature(PhysicalAddress table_header, StringView signature)
|
||||
{
|
||||
// FIXME: There's no validation of ACPI tables here. Use the checksum to validate the tables.
|
||||
VERIFY(signature.length() == 4);
|
||||
|
||||
auto table = Memory::map_typed<Structures::RSDT>(table_header).release_value_but_fixme_should_propagate_errors();
|
||||
return !strncmp(table->h.sig, signature.characters_without_null_termination(), 4);
|
||||
}
|
||||
|
||||
ErrorOr<Optional<PhysicalAddress>> search_table_in_xsdt(PhysicalAddress xsdt_address, StringView signature)
|
||||
{
|
||||
// FIXME: There's no validation of ACPI tables here. Use the checksum to validate the tables.
|
||||
VERIFY(signature.length() == 4);
|
||||
|
||||
auto xsdt = TRY(Memory::map_typed<Structures::XSDT>(xsdt_address));
|
||||
|
||||
for (size_t i = 0; i < ((xsdt->h.length - sizeof(Structures::SDTHeader)) / sizeof(u64)); ++i) {
|
||||
if (match_table_signature(PhysicalAddress((PhysicalPtr)xsdt->table_ptrs[i]), signature))
|
||||
return PhysicalAddress((PhysicalPtr)xsdt->table_ptrs[i]);
|
||||
}
|
||||
return Optional<PhysicalAddress> {};
|
||||
}
|
||||
|
||||
ErrorOr<Optional<PhysicalAddress>> find_table(PhysicalAddress rsdp_address, StringView signature)
|
||||
{
|
||||
// FIXME: There's no validation of ACPI tables here. Use the checksum to validate the tables.
|
||||
VERIFY(signature.length() == 4);
|
||||
|
||||
auto rsdp = TRY(Memory::map_typed<Structures::RSDPDescriptor20>(rsdp_address));
|
||||
|
||||
if (rsdp->base.revision == 0)
|
||||
return search_table_in_rsdt(PhysicalAddress(rsdp->base.rsdt_ptr), signature);
|
||||
|
||||
if (rsdp->base.revision >= 2) {
|
||||
if (rsdp->xsdt_ptr)
|
||||
return search_table_in_xsdt(PhysicalAddress(rsdp->xsdt_ptr), signature);
|
||||
return search_table_in_rsdt(PhysicalAddress(rsdp->base.rsdt_ptr), signature);
|
||||
}
|
||||
VERIFY_NOT_REACHED();
|
||||
}
|
||||
|
||||
ErrorOr<Optional<PhysicalAddress>> search_table_in_rsdt(PhysicalAddress rsdt_address, StringView signature)
|
||||
{
|
||||
// FIXME: There's no validation of ACPI tables here. Use the checksum to validate the tables.
|
||||
VERIFY(signature.length() == 4);
|
||||
|
||||
auto rsdt = TRY(Memory::map_typed<Structures::RSDT>(rsdt_address));
|
||||
|
||||
for (u32 i = 0; i < ((rsdt->h.length - sizeof(Structures::SDTHeader)) / sizeof(u32)); i++) {
|
||||
if (match_table_signature(PhysicalAddress((PhysicalPtr)rsdt->table_ptrs[i]), signature))
|
||||
return PhysicalAddress((PhysicalPtr)rsdt->table_ptrs[i]);
|
||||
}
|
||||
return Optional<PhysicalAddress> {};
|
||||
}
|
||||
|
||||
}
|
24
Kernel/Firmware/ACPI/StaticParsing.h
Normal file
24
Kernel/Firmware/ACPI/StaticParsing.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* Copyright (c) 2023, Liav A. <liavalb@hotmail.co.il>
|
||||
*
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AK/Error.h>
|
||||
#include <AK/Optional.h>
|
||||
#include <AK/Types.h>
|
||||
#include <Kernel/Memory/PhysicalAddress.h>
|
||||
|
||||
namespace Kernel::ACPI::StaticParsing {
|
||||
|
||||
ErrorOr<Optional<PhysicalAddress>> find_table(PhysicalAddress rsdp, StringView signature);
|
||||
ErrorOr<Optional<PhysicalAddress>> search_table_in_xsdt(PhysicalAddress xsdt, StringView signature);
|
||||
ErrorOr<Optional<PhysicalAddress>> search_table_in_rsdt(PhysicalAddress rsdt, StringView signature);
|
||||
|
||||
// NOTE: This function is implemented for each CPU architecture in a subdirectory
|
||||
// under the Kernel/Arch directory.
|
||||
ErrorOr<Optional<PhysicalAddress>> find_rsdp_in_platform_specific_memory_locations();
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue