/* * Copyright (c) 2023, Liav A. * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include 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(table_header).release_value_but_fixme_should_propagate_errors(); return !strncmp(table->h.sig, signature.characters_without_null_termination(), 4); } ErrorOr> 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(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 {}; } ErrorOr> 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(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> 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(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 {}; } }