1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 09:48:11 +00:00

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:
Liav A 2023-06-09 22:50:11 +03:00 committed by Jelle Raaijmakers
parent be16a91aec
commit 428afca32b
11 changed files with 211 additions and 133 deletions

View file

@ -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 {};
}
}