diff --git a/Kernel/ACPI/ACPIStaticParser.cpp b/Kernel/ACPI/ACPIStaticParser.cpp index c9b25dfed3..e944182490 100644 --- a/Kernel/ACPI/ACPIStaticParser.cpp +++ b/Kernel/ACPI/ACPIStaticParser.cpp @@ -212,19 +212,21 @@ void ACPIStaticParser::initialize_main_system_description_table() void ACPIStaticParser::locate_main_system_description_table() { - if (m_rsdp->base.revision == 0) { + auto rsdp_region = MM.allocate_kernel_region(PhysicalAddress(page_base_of((u32)m_rsdp)), (PAGE_SIZE * 2), "ACPI Static Parser Initialization", Region::Access::Read, false, true); + volatile auto* rsdp = (ACPI_RAW::RSDPDescriptor20*)rsdp_region->vaddr().offset(offset_in_page((u32)m_rsdp)).as_ptr(); + if (rsdp->base.revision == 0) { m_xsdt_supported = false; - } else if (m_rsdp->base.revision >= 2) { - if (m_rsdp->xsdt_ptr != (u64) nullptr) { + } else if (rsdp->base.revision >= 2) { + if (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; + m_main_system_description_table = (ACPI_RAW::SDTHeader*)rsdp->base.rsdt_ptr; } else { - m_main_system_description_table = (ACPI_RAW::SDTHeader*)m_rsdp->xsdt_ptr; + m_main_system_description_table = (ACPI_RAW::SDTHeader*)rsdp->xsdt_ptr; } } @@ -265,30 +267,47 @@ ACPIStaticParser::ACPIStaticParser() } } +ACPI_RAW::RSDPDescriptor20* ACPIStaticParser::search_rsdp_in_ebda(u16 ebda_segment) +{ + auto rsdp_region = MM.allocate_kernel_region(PhysicalAddress(page_base_of((u32)(ebda_segment << 4))), PAGE_ROUND_UP(1024), "ACPI Static Parser RSDP Finding #1", Region::Access::Read, false, true); + char* p_rsdp_str = (char*)(PhysicalAddress(ebda_segment << 4).as_ptr()); + for (char* rsdp_str = (char*)rsdp_region->vaddr().offset(offset_in_page((u32)(ebda_segment << 4))).as_ptr(); rsdp_str < (char*)(rsdp_region->vaddr().offset(offset_in_page((u32)(ebda_segment << 4))).get() + 1024); rsdp_str += 16) { +#ifdef ACPI_DEBUG + dbgprintf("ACPI: Looking for RSDP in EBDA @ V0x%x, P0x%x\n", rsdp_str, p_rsdp_str); +#endif + if (!strncmp("RSD PTR ", rsdp_str, strlen("RSD PTR "))) + return (ACPI_RAW::RSDPDescriptor20*)p_rsdp_str; + p_rsdp_str += 16; + } + return nullptr; +} + +ACPI_RAW::RSDPDescriptor20* ACPIStaticParser::search_rsdp_in_bios_area() +{ + auto rsdp_region = MM.allocate_kernel_region(PhysicalAddress(page_base_of((u32)0xE0000)), PAGE_ROUND_UP(0xFFFFF - 0xE0000), "ACPI Static Parser RSDP Finding #2", Region::Access::Read, false, true); + char* p_rsdp_str = (char*)(PhysicalAddress(0xE0000).as_ptr()); + for (char* rsdp_str = (char*)rsdp_region->vaddr().offset(offset_in_page((u32)(0xE0000))).as_ptr(); rsdp_str < (char*)(rsdp_region->vaddr().offset(offset_in_page((u32)(0xE0000))).get() + (0xFFFFF - 0xE0000)); rsdp_str += 16) { +#ifdef ACPI_DEBUG + dbgprintf("ACPI: Looking for RSDP in EBDA @ V0x%x, P0x%x\n", rsdp_str, p_rsdp_str); +#endif + if (!strncmp("RSD PTR ", rsdp_str, strlen("RSD PTR "))) + return (ACPI_RAW::RSDPDescriptor20*)p_rsdp_str; + p_rsdp_str += 16; + } + return nullptr; +} + ACPI_RAW::RSDPDescriptor20* ACPIStaticParser::search_rsdp() { - auto region = MM.allocate_kernel_region(PhysicalAddress((uintptr_t)0), PAGE_SIZE, "ACPI Static Parser RSDP Finding", Region::Access::Read); + ACPI_RAW::RSDPDescriptor20* rsdp = nullptr; + auto region = MM.allocate_kernel_region(PhysicalAddress(0), PAGE_SIZE, "ACPI Static Parser RSDP Finding", Region::Access::Read); 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; + rsdp = search_rsdp_in_ebda(ebda_seg); + if (rsdp != nullptr) + return rsdp; + return search_rsdp_in_bios_area(); } ACPIStaticParser::ACPIStaticParser(ACPI_RAW::RSDPDescriptor20& rsdp) diff --git a/Kernel/ACPI/ACPIStaticParser.h b/Kernel/ACPI/ACPIStaticParser.h index 9dc9cab9fd..6079c2bf7f 100644 --- a/Kernel/ACPI/ACPIStaticParser.h +++ b/Kernel/ACPI/ACPIStaticParser.h @@ -52,6 +52,8 @@ private: size_t get_table_size(ACPI_RAW::SDTHeader&); u8 get_table_revision(ACPI_RAW::SDTHeader&); void init_fadt(); + ACPI_RAW::RSDPDescriptor20* search_rsdp_in_ebda(u16 ebda_segment); + ACPI_RAW::RSDPDescriptor20* search_rsdp_in_bios_area(); ACPI_RAW::RSDPDescriptor20* search_rsdp(); // Early pointers that are needed really for initializtion only...