Repository: SerenityOS/serenity
File: Kernel/Firmware/ACPI/StaticParsing.cpp (C++)

Code before:
#if ARCH(X86_64)
#    include <Kernel/Arch/x86_64/Firmware/ACPI.h>
#endif

namespace Kernel::ACPI::StaticParsing {

Optional<PhysicalAddress> find_rsdp()
{
    Optional<PhysicalAddress> rsdp;
    if (!g_boot_info.acpi_rsdp_paddr.is_null())
        rsdp = g_boot_info.acpi_rsdp_paddr;

#if ARCH(X86_64)
    if (!rsdp.has_value() && g_boot_info.boot_method == BootMethod::Multiboot1)
        rsdp = StaticParsing::find_rsdp_in_ia_pc_specific_memory_locations();
#endif

    return rsdp;
}

static bool match_table_signature(PhysicalAddress table_header, StringView signature)
{
    VERIFY(signature.length() == 4);

    auto check_in_region = [&](size_t length, auto&& callback) -> bool {
        auto mapping_length = MUST(Memory::page_round_up(table_header.offset_in_page() + length));
        auto region = MUST(MM.allocate_mmio_kernel_region(table_header.page_base(), mapping_length, {}, Memory::Region::Access::Read));
        u8 const* base = region->vaddr().offset(table_header.offset_in_page()).as_ptr();
        return callback(base);
    };

    u32 length = 0;
    auto check_signature_and_get_length = [&](u8 const* base) -> bool {
        if (strncmp(reinterpret_cast<char const*>(base), signature.characters_without_null_termination(), 4) != 0)
            return false;
        length = ByteReader::load32(base + 4);
        return true;
    };

    auto validate_checksum = [&](u8 const* base) -> bool {
        u8 checksum = 0;
        for (u32 i = 0; i < length; ++i)
            checksum += base[i];
        return checksum == 0;
    };

    return check_in_region(8, check_signature_and_get_length) && check_in_region(length, validate_checksum);
}

ErrorOr<Optional<PhysicalAddress>> search_table_in_xsdt(PhysicalAddress xsdt_address, StringView signature)
{

Review comment (suggestion):
Maybe (ab)use `Memory::map_typed<u8 const>` here?

I know this might be a bit awkward, but we do this in other places as well and gets rid of the manual offset calculations.

Code after:
#if ARCH(X86_64)
#    include <Kernel/Arch/x86_64/Firmware/ACPI.h>
#endif

namespace Kernel::ACPI::StaticParsing {

Optional<PhysicalAddress> find_rsdp()
{
    Optional<PhysicalAddress> rsdp;
    if (!g_boot_info.acpi_rsdp_paddr.is_null())
        rsdp = g_boot_info.acpi_rsdp_paddr;

#if ARCH(X86_64)
    if (!rsdp.has_value() && g_boot_info.boot_method == BootMethod::Multiboot1)
        rsdp = StaticParsing::find_rsdp_in_ia_pc_specific_memory_locations();
#endif

    return rsdp;
}

static bool match_table_signature(PhysicalAddress table_header, StringView signature)
{
    VERIFY(signature.length() == 4);

    auto check_in_region = [&](size_t length, auto&& callback) -> bool {
        auto region = Memory::map_typed<u8 const>(table_header, length).release_value_but_fixme_should_propagate_errors();
        return callback(region.ptr());
    };

    u32 length = 0;
    auto check_signature_and_get_length = [&](u8 const* base) -> bool {
        if (memcmp(reinterpret_cast<char const*>(base), signature.characters_without_null_termination(), 4) != 0)
            return false;
        length = ByteReader::load32(base + 4);
        return true;
    };

    auto validate_checksum = [&](u8 const* base) -> bool {
        u8 checksum = 0;
        for (u32 i = 0; i < length; ++i)
            checksum += base[i];
        return checksum == 0;
    };

    return check_in_region(8, check_signature_and_get_length) && check_in_region(length, validate_checksum);
}

ErrorOr<Optional<PhysicalAddress>> search_table_in_xsdt(PhysicalAddress xsdt_address, StringView signature)
{
    VERIFY(signature.length() == 4);