瀏覽代碼

Kernel: ACPI code doesn't rely on identity mapping anymore

The problem was mostly in the initialization code, since in that stage
the parser assumed that there is an identity mapping in the first 1MB of
the address space. Now during initialization the parser will create the
correct mappings to locate the required data.
Liav A 5 年之前
父節點
當前提交
60c32f44dd
共有 2 個文件被更改,包括 39 次插入18 次删除
  1. 37 18
      Kernel/ACPI/ACPIStaticParser.cpp
  2. 2 0
      Kernel/ACPI/ACPIStaticParser.h

+ 37 - 18
Kernel/ACPI/ACPIStaticParser.cpp

@@ -212,19 +212,21 @@ void ACPIStaticParser::initialize_main_system_description_table()
 
 
 void ACPIStaticParser::locate_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;
         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;
             m_xsdt_supported = true;
         } else {
         } else {
             m_xsdt_supported = false;
             m_xsdt_supported = false;
         }
         }
     }
     }
     if (!m_xsdt_supported) {
     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 {
     } 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,32 +267,49 @@ ACPIStaticParser::ACPIStaticParser()
     }
     }
 }
 }
 
 
-ACPI_RAW::RSDPDescriptor20* ACPIStaticParser::search_rsdp()
+ACPI_RAW::RSDPDescriptor20* ACPIStaticParser::search_rsdp_in_ebda(u16 ebda_segment)
 {
 {
-    auto region = MM.allocate_kernel_region(PhysicalAddress((uintptr_t)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) {
+    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
 #ifdef ACPI_DEBUG
-        dbgprintf("ACPI: Looking for RSDP in EBDA @ Px%x\n", rsdp_str);
+        dbgprintf("ACPI: Looking for RSDP in EBDA @ V0x%x, P0x%x\n", rsdp_str, p_rsdp_str);
 #endif
 #endif
         if (!strncmp("RSD PTR ", rsdp_str, strlen("RSD PTR ")))
         if (!strncmp("RSD PTR ", rsdp_str, strlen("RSD PTR ")))
-            return (ACPI_RAW::RSDPDescriptor20*)rsdp_str;
+            return (ACPI_RAW::RSDPDescriptor20*)p_rsdp_str;
+        p_rsdp_str += 16;
     }
     }
+    return nullptr;
+}
 
 
-    // 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) {
+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
 #ifdef ACPI_DEBUG
-        dbgprintf("ACPI: Looking for RSDP in EBDA @ Px%x\n", rsdp_str);
+        dbgprintf("ACPI: Looking for RSDP in EBDA @ V0x%x, P0x%x\n", rsdp_str, p_rsdp_str);
 #endif
 #endif
         if (!strncmp("RSD PTR ", rsdp_str, strlen("RSD PTR ")))
         if (!strncmp("RSD PTR ", rsdp_str, strlen("RSD PTR ")))
-            return (ACPI_RAW::RSDPDescriptor20*)rsdp_str;
+            return (ACPI_RAW::RSDPDescriptor20*)p_rsdp_str;
+        p_rsdp_str += 16;
     }
     }
     return nullptr;
     return nullptr;
 }
 }
 
 
+ACPI_RAW::RSDPDescriptor20* ACPIStaticParser::search_rsdp()
+{
+    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);
+
+    rsdp = search_rsdp_in_ebda(ebda_seg);
+    if (rsdp != nullptr)
+        return rsdp;
+    return search_rsdp_in_bios_area();
+}
+
 ACPIStaticParser::ACPIStaticParser(ACPI_RAW::RSDPDescriptor20& rsdp)
 ACPIStaticParser::ACPIStaticParser(ACPI_RAW::RSDPDescriptor20& rsdp)
     : ACPIParser(true)
     : ACPIParser(true)
     , m_rsdp(&rsdp)
     , m_rsdp(&rsdp)

+ 2 - 0
Kernel/ACPI/ACPIStaticParser.h

@@ -52,6 +52,8 @@ private:
     size_t get_table_size(ACPI_RAW::SDTHeader&);
     size_t get_table_size(ACPI_RAW::SDTHeader&);
     u8 get_table_revision(ACPI_RAW::SDTHeader&);
     u8 get_table_revision(ACPI_RAW::SDTHeader&);
     void init_fadt();
     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();
     ACPI_RAW::RSDPDescriptor20* search_rsdp();
 
 
     // Early pointers that are needed really for initializtion only...
     // Early pointers that are needed really for initializtion only...