mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 15:42:44 +00:00 
			
		
		
		
	Kernel: Add typed_map<T>(PhysicalAddress) and use it in ACPI parsing
There was a frequently occurring pattern of "map this physical address into kernel VM, then read from it, then unmap it again". This new typed_map() encapsulates that logic by giving you back a typed pointer to the kind of structure you're interested in accessing. It returns a TypedMapping<T> that can be used mostly like a pointer. When destroyed, the TypedMapping object will unmap the memory. :^)
This commit is contained in:
		
							parent
							
								
									4644217094
								
							
						
					
					
						commit
						f614f0e2cb
					
				
					 5 changed files with 140 additions and 98 deletions
				
			
		|  | @ -28,6 +28,7 @@ | ||||||
| #include <Kernel/ACPI/ACPIStaticParser.h> | #include <Kernel/ACPI/ACPIStaticParser.h> | ||||||
| #include <Kernel/PCI/Access.h> | #include <Kernel/PCI/Access.h> | ||||||
| #include <Kernel/VM/MemoryManager.h> | #include <Kernel/VM/MemoryManager.h> | ||||||
|  | #include <Kernel/VM/TypedMapping.h> | ||||||
| #include <LibBareMetal/IO.h> | #include <LibBareMetal/IO.h> | ||||||
| #include <LibBareMetal/StdLib.h> | #include <LibBareMetal/StdLib.h> | ||||||
| 
 | 
 | ||||||
|  | @ -50,8 +51,7 @@ PhysicalAddress StaticParser::find_table(const char* sig) | ||||||
|     dbg() << "ACPI: Calling Find Table method!"; |     dbg() << "ACPI: Calling Find Table method!"; | ||||||
| #endif | #endif | ||||||
|     for (auto p_sdt : m_sdt_pointers) { |     for (auto p_sdt : m_sdt_pointers) { | ||||||
|         auto region = MM.allocate_kernel_region(p_sdt.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser Tables Finding", Region::Access::Read); |         auto sdt = map_typed<Structures::SDTHeader>(p_sdt); | ||||||
|         auto* sdt = (const Structures::SDTHeader*)region->vaddr().offset(p_sdt.offset_in_page()).as_ptr(); |  | ||||||
| #ifdef ACPI_DEBUG | #ifdef ACPI_DEBUG | ||||||
|         dbg() << "ACPI: Examining Table @ P " << p_sdt; |         dbg() << "ACPI: Examining Table @ P " << p_sdt; | ||||||
| #endif | #endif | ||||||
|  | @ -87,8 +87,8 @@ void StaticParser::init_fadt() | ||||||
|     m_fadt = find_table("FACP"); |     m_fadt = find_table("FACP"); | ||||||
|     ASSERT(!m_fadt.is_null()); |     ASSERT(!m_fadt.is_null()); | ||||||
| 
 | 
 | ||||||
|     auto checkup_region = MM.allocate_kernel_region(m_fadt.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser", Region::Access::Read); |     auto sdt = map_typed<Structures::FADT>(m_fadt); | ||||||
|     auto* sdt = (const Structures::FADT*)checkup_region->vaddr().offset(m_fadt.offset_in_page()).as_ptr(); | 
 | ||||||
| #ifdef ACPI_DEBUG | #ifdef ACPI_DEBUG | ||||||
|     dbg() << "ACPI: FADT @ V " << sdt << ", P " << (void*)m_fadt.as_ptr(); |     dbg() << "ACPI: FADT @ V " << sdt << ", P " << (void*)m_fadt.as_ptr(); | ||||||
| #endif | #endif | ||||||
|  | @ -126,8 +126,7 @@ void StaticParser::init_fadt() | ||||||
| 
 | 
 | ||||||
| bool StaticParser::can_reboot() | bool StaticParser::can_reboot() | ||||||
| { | { | ||||||
|     auto region = MM.allocate_kernel_region(m_fadt.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser", Region::Access::Read); |     auto fadt = map_typed<Structures::FADT>(m_fadt); | ||||||
|     auto* fadt = (const Structures::FADT*)region->vaddr().offset(m_fadt.offset_in_page()).as_ptr(); |  | ||||||
|     if (fadt->h.revision < 2) |     if (fadt->h.revision < 2) | ||||||
|         return false; |         return false; | ||||||
|     return m_hardware_flags.reset_register_supported; |     return m_hardware_flags.reset_register_supported; | ||||||
|  | @ -135,8 +134,8 @@ bool StaticParser::can_reboot() | ||||||
| 
 | 
 | ||||||
| void StaticParser::access_generic_address(const Structures::GenericAddressStructure& structure, u32 value) | void StaticParser::access_generic_address(const Structures::GenericAddressStructure& structure, u32 value) | ||||||
| { | { | ||||||
|     switch (structure.address_space) { |     switch ((GenericAddressStructure::AddressSpace)structure.address_space) { | ||||||
|     case (u8)GenericAddressStructure::AddressSpace::SystemIO: { |     case GenericAddressStructure::AddressSpace::SystemIO: { | ||||||
|         IOAddress address(structure.address); |         IOAddress address(structure.address); | ||||||
|         dbg() << "ACPI: Sending value 0x" << String::format("%x", value) << " to " << address; |         dbg() << "ACPI: Sending value 0x" << String::format("%x", value) << " to " << address; | ||||||
|         switch (structure.access_size) { |         switch (structure.access_size) { | ||||||
|  | @ -159,29 +158,20 @@ void StaticParser::access_generic_address(const Structures::GenericAddressStruct | ||||||
|         } |         } | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     case (u8)GenericAddressStructure::AddressSpace::SystemMemory: { |     case GenericAddressStructure::AddressSpace::SystemMemory: { | ||||||
|         auto p_reg = PhysicalAddress(structure.address); |         dbg() << "ACPI: Sending value 0x" << String::format("%x", value) << " to " << PhysicalAddress(structure.address); | ||||||
|         auto p_region = MM.allocate_kernel_region(p_reg.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser", Region::Access::Read); |         switch ((GenericAddressStructure::AccessSize)structure.access_size) { | ||||||
|         dbg() << "ACPI: Sending value 0x" << String::format("%x", value) << " to " << p_reg; |         case GenericAddressStructure::AccessSize::Byte: | ||||||
|         switch (structure.access_size) { |             *map_typed<u8>(PhysicalAddress(structure.address)) = value; | ||||||
|         case (u8)GenericAddressStructure::AccessSize::Byte: { |  | ||||||
|             auto* reg = (volatile u8*)p_region->vaddr().offset(p_reg.offset_in_page()).as_ptr(); |  | ||||||
|             (*reg) = value; |  | ||||||
|             break; |             break; | ||||||
|         } |         case GenericAddressStructure::AccessSize::Word: | ||||||
|         case (u8)GenericAddressStructure::AccessSize::Word: { |             *map_typed<u16>(PhysicalAddress(structure.address)) = value; | ||||||
|             auto* reg = (volatile u16*)p_region->vaddr().offset(p_reg.offset_in_page()).as_ptr(); |  | ||||||
|             (*reg) = value; |  | ||||||
|             break; |             break; | ||||||
|         } |         case GenericAddressStructure::AccessSize::DWord: | ||||||
|         case (u8)GenericAddressStructure::AccessSize::DWord: { |             *map_typed<u32>(PhysicalAddress(structure.address)) = value; | ||||||
|             auto* reg = (volatile u32*)p_region->vaddr().offset(p_reg.offset_in_page()).as_ptr(); |  | ||||||
|             (*reg) = value; |  | ||||||
|             break; |             break; | ||||||
|         } |         case GenericAddressStructure::AccessSize::QWord: { | ||||||
|         case (u8)GenericAddressStructure::AccessSize::QWord: { |             *map_typed<u64>(PhysicalAddress(structure.address)) = value; | ||||||
|             auto* reg = (volatile u64*)p_region->vaddr().offset(p_reg.offset_in_page()).as_ptr(); |  | ||||||
|             (*reg) = value; |  | ||||||
|             break; |             break; | ||||||
|         } |         } | ||||||
|         default: |         default: | ||||||
|  | @ -189,7 +179,7 @@ void StaticParser::access_generic_address(const Structures::GenericAddressStruct | ||||||
|         } |         } | ||||||
|         return; |         return; | ||||||
|     } |     } | ||||||
|     case (u8)GenericAddressStructure::AddressSpace::PCIConfigurationSpace: { |     case GenericAddressStructure::AddressSpace::PCIConfigurationSpace: { | ||||||
|         // According to the ACPI specification 6.2, page 168, PCI addresses must be confined to devices on Segment group 0, bus 0.
 |         // According to the ACPI specification 6.2, page 168, PCI addresses must be confined to devices on Segment group 0, bus 0.
 | ||||||
|         auto pci_address = PCI::Address(0, 0, ((structure.address >> 24) & 0xFF), ((structure.address >> 16) & 0xFF)); |         auto pci_address = PCI::Address(0, 0, ((structure.address >> 24) & 0xFF), ((structure.address >> 16) & 0xFF)); | ||||||
|         dbg() << "ACPI: Sending value 0x" << String::format("%x", value) << " to " << pci_address; |         dbg() << "ACPI: Sending value 0x" << String::format("%x", value) << " to " << pci_address; | ||||||
|  | @ -211,8 +201,7 @@ void StaticParser::access_generic_address(const Structures::GenericAddressStruct | ||||||
| bool StaticParser::validate_reset_register() | bool StaticParser::validate_reset_register() | ||||||
| { | { | ||||||
|     // According to the ACPI spec 6.2, page 152, The reset register can only be located in I/O bus, PCI bus or memory-mapped.
 |     // According to the ACPI spec 6.2, page 152, The reset register can only be located in I/O bus, PCI bus or memory-mapped.
 | ||||||
|     auto region = MM.allocate_kernel_region(m_fadt.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser", Region::Access::Read); |     auto fadt = map_typed<Structures::FADT>(m_fadt); | ||||||
|     auto* fadt = (const Structures::FADT*)region->vaddr().offset(m_fadt.offset_in_page()).as_ptr(); |  | ||||||
|     return (fadt->reset_reg.address_space == (u8)GenericAddressStructure::AddressSpace::PCIConfigurationSpace || fadt->reset_reg.address_space == (u8)GenericAddressStructure::AddressSpace::SystemMemory || fadt->reset_reg.address_space == (u8)GenericAddressStructure::AddressSpace::SystemIO); |     return (fadt->reset_reg.address_space == (u8)GenericAddressStructure::AddressSpace::PCIConfigurationSpace || fadt->reset_reg.address_space == (u8)GenericAddressStructure::AddressSpace::SystemMemory || fadt->reset_reg.address_space == (u8)GenericAddressStructure::AddressSpace::SystemIO); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | @ -227,12 +216,10 @@ void StaticParser::try_acpi_reboot() | ||||||
|     dbg() << "ACPI: Rebooting, Probing FADT (" << m_fadt << ")"; |     dbg() << "ACPI: Rebooting, Probing FADT (" << m_fadt << ")"; | ||||||
| #endif | #endif | ||||||
| 
 | 
 | ||||||
|     auto region = MM.allocate_kernel_region(m_fadt.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser", Region::Access::Read); |     auto fadt = map_typed<Structures::FADT>(m_fadt); | ||||||
|     auto* fadt = (const Structures::FADT*)region->vaddr().offset(m_fadt.offset_in_page()).as_ptr(); |  | ||||||
|     ASSERT(validate_reset_register()); |     ASSERT(validate_reset_register()); | ||||||
|     access_generic_address(fadt->reset_reg, fadt->reset_value); |     access_generic_address(fadt->reset_reg, fadt->reset_value); | ||||||
|     for (;;) |     hang(); | ||||||
|         ; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void StaticParser::try_acpi_shutdown() | void StaticParser::try_acpi_shutdown() | ||||||
|  | @ -246,9 +233,7 @@ size_t StaticParser::get_table_size(PhysicalAddress table_header) | ||||||
| #ifdef ACPI_DEBUG | #ifdef ACPI_DEBUG | ||||||
|     dbg() << "ACPI: Checking SDT Length"; |     dbg() << "ACPI: Checking SDT Length"; | ||||||
| #endif | #endif | ||||||
|     auto region = MM.allocate_kernel_region(table_header.page_base(), (PAGE_SIZE * 2), "ACPI get_table_size()", Region::Access::Read); |     return map_typed<Structures::SDTHeader>(table_header)->length; | ||||||
|     auto* sdt = (volatile Structures::SDTHeader*)region->vaddr().offset(table_header.offset_in_page()).as_ptr(); |  | ||||||
|     return sdt->length; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| u8 StaticParser::get_table_revision(PhysicalAddress table_header) | u8 StaticParser::get_table_revision(PhysicalAddress table_header) | ||||||
|  | @ -257,9 +242,7 @@ u8 StaticParser::get_table_revision(PhysicalAddress table_header) | ||||||
| #ifdef ACPI_DEBUG | #ifdef ACPI_DEBUG | ||||||
|     dbg() << "ACPI: Checking SDT Revision"; |     dbg() << "ACPI: Checking SDT Revision"; | ||||||
| #endif | #endif | ||||||
|     auto region = MM.allocate_kernel_region(table_header.page_base(), (PAGE_SIZE * 2), "ACPI get_table_revision()", Region::Access::Read); |     return map_typed<Structures::SDTHeader>(table_header)->revision; | ||||||
|     auto* sdt = (volatile Structures::SDTHeader*)region->vaddr().offset(table_header.offset_in_page()).as_ptr(); |  | ||||||
|     return sdt->revision; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void StaticParser::initialize_main_system_description_table() | void StaticParser::initialize_main_system_description_table() | ||||||
|  | @ -271,12 +254,12 @@ void StaticParser::initialize_main_system_description_table() | ||||||
|     auto length = get_table_size(m_main_system_description_table); |     auto length = get_table_size(m_main_system_description_table); | ||||||
|     auto revision = get_table_revision(m_main_system_description_table); |     auto revision = get_table_revision(m_main_system_description_table); | ||||||
| 
 | 
 | ||||||
|     auto main_sdt_region = MM.allocate_kernel_region(m_main_system_description_table.page_base(), PAGE_ROUND_UP(length) + PAGE_SIZE, "ACPI Static Parser Initialization", Region::Access::Read, false, true); |     auto sdt = map_typed<Structures::SDTHeader>(m_main_system_description_table, length); | ||||||
|     auto* sdt = (volatile Structures::SDTHeader*)main_sdt_region->vaddr().offset(m_main_system_description_table.offset_in_page()).as_ptr(); | 
 | ||||||
|     klog() << "ACPI: Main Description Table valid? " << StaticParsing::validate_table(const_cast<Structures::SDTHeader&>(*sdt), length); |     klog() << "ACPI: Main Description Table valid? " << StaticParsing::validate_table(*sdt, length); | ||||||
| 
 | 
 | ||||||
|     if (m_xsdt_supported) { |     if (m_xsdt_supported) { | ||||||
|         volatile auto* xsdt = (volatile Structures::XSDT*)sdt; |         auto& xsdt = (const Structures::XSDT&)*sdt; | ||||||
|         klog() << "ACPI: Using XSDT, Enumerating tables @ " << m_main_system_description_table; |         klog() << "ACPI: Using XSDT, Enumerating tables @ " << m_main_system_description_table; | ||||||
|         klog() << "ACPI: XSDT Revision " << revision << ", Total length - " << length; |         klog() << "ACPI: XSDT Revision " << revision << ", Total length - " << length; | ||||||
| #ifdef ACPI_DEBUG | #ifdef ACPI_DEBUG | ||||||
|  | @ -284,12 +267,12 @@ void StaticParser::initialize_main_system_description_table() | ||||||
| #endif | #endif | ||||||
|         for (u32 i = 0; i < ((length - sizeof(Structures::SDTHeader)) / sizeof(u64)); i++) { |         for (u32 i = 0; i < ((length - sizeof(Structures::SDTHeader)) / sizeof(u64)); i++) { | ||||||
| #ifdef ACPI_DEBUG | #ifdef ACPI_DEBUG | ||||||
|             dbg() << "ACPI: Found new table [" << i << "], @ V 0x" << String::format("%x", &xsdt->table_ptrs[i]) << " - P 0x" << String::format("%x", xsdt->table_ptrs[i]); |             dbg() << "ACPI: Found new table [" << i << "], @ V 0x" << String::format("%x", &xsdt.table_ptrs[i]) << " - P 0x" << String::format("%x", xsdt.table_ptrs[i]); | ||||||
| #endif | #endif | ||||||
|             m_sdt_pointers.append(PhysicalAddress(xsdt->table_ptrs[i])); |             m_sdt_pointers.append(PhysicalAddress(xsdt.table_ptrs[i])); | ||||||
|         } |         } | ||||||
|     } else { |     } else { | ||||||
|         volatile auto* rsdt = (volatile Structures::RSDT*)sdt; |         auto& rsdt = (const Structures::RSDT&)*sdt; | ||||||
|         klog() << "ACPI: Using RSDT, Enumerating tables @ " << m_main_system_description_table; |         klog() << "ACPI: Using RSDT, Enumerating tables @ " << m_main_system_description_table; | ||||||
|         klog() << "ACPI: RSDT Revision " << revision << ", Total length - " << length; |         klog() << "ACPI: RSDT Revision " << revision << ", Total length - " << length; | ||||||
| #ifdef ACPI_DEBUG | #ifdef ACPI_DEBUG | ||||||
|  | @ -297,17 +280,16 @@ void StaticParser::initialize_main_system_description_table() | ||||||
| #endif | #endif | ||||||
|         for (u32 i = 0; i < ((length - sizeof(Structures::SDTHeader)) / sizeof(u32)); i++) { |         for (u32 i = 0; i < ((length - sizeof(Structures::SDTHeader)) / sizeof(u32)); i++) { | ||||||
| #ifdef ACPI_DEBUG | #ifdef ACPI_DEBUG | ||||||
|             dbg() << "ACPI: Found new table [" << i << "], @ V 0x" << String::format("%x", &rsdt->table_ptrs[i]) << " - P 0x" << String::format("%x", rsdt->table_ptrs[i]); |             dbg() << "ACPI: Found new table [" << i << "], @ V 0x" << String::format("%x", &rsdt.table_ptrs[i]) << " - P 0x" << String::format("%x", rsdt.table_ptrs[i]); | ||||||
| #endif | #endif | ||||||
|             m_sdt_pointers.append(PhysicalAddress(rsdt->table_ptrs[i])); |             m_sdt_pointers.append(PhysicalAddress(rsdt.table_ptrs[i])); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void StaticParser::locate_main_system_description_table() | void StaticParser::locate_main_system_description_table() | ||||||
| { | { | ||||||
|     auto rsdp_region = MM.allocate_kernel_region(m_rsdp.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser Initialization", Region::Access::Read, false, true); |     auto rsdp = map_typed<Structures::RSDPDescriptor20>(m_rsdp); | ||||||
|     volatile auto* rsdp = (Structures::RSDPDescriptor20*)rsdp_region->vaddr().offset(m_rsdp.offset_in_page()).as_ptr(); |  | ||||||
|     if (rsdp->base.revision == 0) { |     if (rsdp->base.revision == 0) { | ||||||
|         m_xsdt_supported = false; |         m_xsdt_supported = false; | ||||||
|     } else if (rsdp->base.revision >= 2) { |     } else if (rsdp->base.revision >= 2) { | ||||||
|  | @ -331,7 +313,7 @@ StaticParser::StaticParser(PhysicalAddress rsdp) | ||||||
|     locate_static_data(); |     locate_static_data(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| PhysicalAddress StaticParsing::search_rsdp_in_ebda(u16 ebda_segment) | static PhysicalAddress find_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); |     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()); |     char* p_rsdp_str = (char*)(PhysicalAddress(ebda_segment << 4).as_ptr()); | ||||||
|  | @ -346,7 +328,7 @@ PhysicalAddress StaticParsing::search_rsdp_in_ebda(u16 ebda_segment) | ||||||
|     return {}; |     return {}; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| PhysicalAddress StaticParsing::search_rsdp_in_bios_area() | static PhysicalAddress find_rsdp_in_bios_area() | ||||||
| { | { | ||||||
|     auto rsdp_region = MM.allocate_kernel_region(PhysicalAddress(0xE0000), PAGE_ROUND_UP(0xFFFFF - 0xE0000), "ACPI Static Parser RSDP Finding #2", Region::Access::Read, false, true); |     auto rsdp_region = MM.allocate_kernel_region(PhysicalAddress(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()); |     char* p_rsdp_str = (char*)(PhysicalAddress(0xE0000).as_ptr()); | ||||||
|  | @ -361,10 +343,10 @@ PhysicalAddress StaticParsing::search_rsdp_in_bios_area() | ||||||
|     return {}; |     return {}; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| inline bool StaticParsing::validate_table(Structures::SDTHeader& v_header, size_t length) | inline bool StaticParsing::validate_table(const Structures::SDTHeader& v_header, size_t length) | ||||||
| { | { | ||||||
|     u8 checksum = 0; |     u8 checksum = 0; | ||||||
|     auto* sdt = (u8*)&v_header; |     auto* sdt = (const u8*)&v_header; | ||||||
|     for (size_t i = 0; i < length; i++) |     for (size_t i = 0; i < length; i++) | ||||||
|         checksum += sdt[i]; |         checksum += sdt[i]; | ||||||
|     if (checksum == 0) |     if (checksum == 0) | ||||||
|  | @ -372,49 +354,46 @@ inline bool StaticParsing::validate_table(Structures::SDTHeader& v_header, size_ | ||||||
|     return false; |     return false; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| PhysicalAddress StaticParsing::search_rsdp() | PhysicalAddress StaticParsing::find_rsdp() | ||||||
| { | { | ||||||
|     PhysicalAddress rsdp; |     auto ebda_seg_ptr = map_typed<u16>(PhysicalAddress(0x40e)); | ||||||
|     auto region = MM.allocate_kernel_region(PhysicalAddress(0), PAGE_SIZE, "ACPI RSDP Searching", Region::Access::Read); |     klog() << "ACPI: Probing EBDA, Segment 0x" << String::format("%x", *ebda_seg_ptr); | ||||||
|     u16 ebda_seg = (u16) * ((uint16_t*)((region->vaddr().get() & PAGE_MASK) + 0x40e)); |     auto rsdp = find_rsdp_in_ebda(*ebda_seg_ptr); | ||||||
|     klog() << "ACPI: Probing EBDA, Segment 0x" << String::format("%x", ebda_seg); |  | ||||||
| 
 |  | ||||||
|     rsdp = search_rsdp_in_ebda(ebda_seg); |  | ||||||
|     if (!rsdp.is_null()) |     if (!rsdp.is_null()) | ||||||
|         return rsdp; |         return rsdp; | ||||||
|     return search_rsdp_in_bios_area(); |     return find_rsdp_in_bios_area(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| PhysicalAddress StaticParsing::search_table(PhysicalAddress rsdp, const char* signature) | PhysicalAddress StaticParsing::search_table(PhysicalAddress rsdp_address, const char* signature) | ||||||
| { | { | ||||||
|     // FIXME: There's no validation of ACPI tables here. Use the checksum to validate the tables.
 |     // FIXME: There's no validation of ACPI tables here. Use the checksum to validate the tables.
 | ||||||
|     // FIXME: Don't blindly use PAGE_SIZE here, but probe the actual length.
 |     // FIXME: Don't blindly use PAGE_SIZE here, but probe the actual length.
 | ||||||
| 
 |  | ||||||
|     ASSERT(strlen(signature) == 4); |     ASSERT(strlen(signature) == 4); | ||||||
|     auto rsdp_region = MM.allocate_kernel_region(rsdp.page_base(), (PAGE_SIZE * 2), "ACPI Static Parsing search_table()", Region::Access::Read, false, true); | 
 | ||||||
|     volatile auto* rsdp_ptr = (Structures::RSDPDescriptor20*)rsdp_region->vaddr().offset(rsdp.offset_in_page()).as_ptr(); |     auto rsdp = map_typed<Structures::RSDPDescriptor20>(rsdp_address); | ||||||
|     if (rsdp_ptr->base.revision == 0) { | 
 | ||||||
|         return search_table_in_rsdt(PhysicalAddress(rsdp_ptr->base.rsdt_ptr), signature); |     if (rsdp->base.revision == 0) | ||||||
|     } |         return search_table_in_rsdt(PhysicalAddress(rsdp->base.rsdt_ptr), signature); | ||||||
|     if (rsdp_ptr->base.revision >= 2) { | 
 | ||||||
|         if (rsdp_ptr->xsdt_ptr != (u64) nullptr) |     if (rsdp->base.revision >= 2) { | ||||||
|             return search_table_in_xsdt(PhysicalAddress(rsdp_ptr->xsdt_ptr), signature); |         if (rsdp->xsdt_ptr) | ||||||
|         return search_table_in_rsdt(PhysicalAddress(rsdp_ptr->base.rsdt_ptr), signature); |             return search_table_in_xsdt(PhysicalAddress(rsdp->xsdt_ptr), signature); | ||||||
|  |         return search_table_in_rsdt(PhysicalAddress(rsdp->base.rsdt_ptr), signature); | ||||||
|     } |     } | ||||||
|     ASSERT_NOT_REACHED(); |     ASSERT_NOT_REACHED(); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| PhysicalAddress StaticParsing::search_table_in_xsdt(PhysicalAddress xsdt, const char* signature) | PhysicalAddress StaticParsing::search_table_in_xsdt(PhysicalAddress xsdt_address, const char* signature) | ||||||
| { | { | ||||||
|     // FIXME: There's no validation of ACPI tables here. Use the checksum to validate the tables.
 |     // FIXME: There's no validation of ACPI tables here. Use the checksum to validate the tables.
 | ||||||
|     // FIXME: Don't blindly use PAGE_SIZE here, but probe the actual length.
 |     // FIXME: Don't blindly use PAGE_SIZE here, but probe the actual length.
 | ||||||
| 
 |  | ||||||
|     ASSERT(strlen(signature) == 4); |     ASSERT(strlen(signature) == 4); | ||||||
|     auto main_sdt_region = MM.allocate_kernel_region(xsdt.page_base(), PAGE_SIZE, "ACPI Static Parsing search_table_in_xsdt()", Region::Access::Read, false, true); | 
 | ||||||
|     auto* xsdt_ptr = (volatile Structures::XSDT*)main_sdt_region->vaddr().offset(xsdt.offset_in_page()).as_ptr(); |     auto xsdt = map_typed<Structures::XSDT>(xsdt_address); | ||||||
|     for (u32 i = 0; i < ((xsdt_ptr->h.length - sizeof(Structures::SDTHeader)) / sizeof(u64)); i++) { | 
 | ||||||
|         if (match_table_signature(PhysicalAddress((FlatPtr)xsdt_ptr->table_ptrs[i]), signature)) |     for (size_t i = 0; i < ((xsdt->h.length - sizeof(Structures::SDTHeader)) / sizeof(u64)); ++i) { | ||||||
|             return PhysicalAddress((FlatPtr)xsdt_ptr->table_ptrs[i]); |         if (match_table_signature(PhysicalAddress((FlatPtr)xsdt->table_ptrs[i]), signature)) | ||||||
|  |             return PhysicalAddress((FlatPtr)xsdt->table_ptrs[i]); | ||||||
|     } |     } | ||||||
|     return {}; |     return {}; | ||||||
| } | } | ||||||
|  | @ -423,27 +402,26 @@ bool StaticParsing::match_table_signature(PhysicalAddress table_header, const ch | ||||||
| { | { | ||||||
|     // FIXME: There's no validation of ACPI tables here. Use the checksum to validate the tables.
 |     // FIXME: There's no validation of ACPI tables here. Use the checksum to validate the tables.
 | ||||||
|     // FIXME: Don't blindly use PAGE_SIZE here, but probe the actual length.
 |     // FIXME: Don't blindly use PAGE_SIZE here, but probe the actual length.
 | ||||||
| 
 |  | ||||||
|     ASSERT(strlen(signature) == 4); |     ASSERT(strlen(signature) == 4); | ||||||
|     auto main_sdt_region = MM.allocate_kernel_region(table_header.page_base(), PAGE_SIZE, "ACPI Static Parsing match_table_signature()", Region::Access::Read, false, true); | 
 | ||||||
|     auto* table_ptr = (volatile Structures::RSDT*)main_sdt_region->vaddr().offset(table_header.offset_in_page()).as_ptr(); |     auto table = map_typed<Structures::RSDT>(table_header); | ||||||
|     return !strncmp(const_cast<const char*>(table_ptr->h.sig), signature, 4); |     return !strncmp(table->h.sig, signature, 4); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| PhysicalAddress StaticParsing::search_table_in_rsdt(PhysicalAddress rsdt, const char* signature) | PhysicalAddress StaticParsing::search_table_in_rsdt(PhysicalAddress rsdt_address, const char* signature) | ||||||
| { | { | ||||||
|     // FIXME: There's no validation of ACPI tables here. Use the checksum to validate the tables.
 |     // FIXME: There's no validation of ACPI tables here. Use the checksum to validate the tables.
 | ||||||
|     // FIXME: Don't blindly use PAGE_SIZE here, but probe the actual length.
 |     // FIXME: Don't blindly use PAGE_SIZE here, but probe the actual length.
 | ||||||
|     ASSERT(strlen(signature) == 4); |     ASSERT(strlen(signature) == 4); | ||||||
| 
 | 
 | ||||||
|     auto main_sdt_region = MM.allocate_kernel_region(rsdt.page_base(), PAGE_SIZE, "ACPI Static Parsing search_table_in_rsdt()", Region::Access::Read, false, true); |     auto rsdt = map_typed<Structures::RSDT>(rsdt_address); | ||||||
|     auto* rsdt_ptr = (volatile Structures::RSDT*)main_sdt_region->vaddr().offset(rsdt.offset_in_page()).as_ptr(); |  | ||||||
| 
 | 
 | ||||||
|     for (u32 i = 0; i < ((rsdt_ptr->h.length - sizeof(Structures::SDTHeader)) / sizeof(u32)); i++) { |     for (u32 i = 0; i < ((rsdt->h.length - sizeof(Structures::SDTHeader)) / sizeof(u32)); i++) { | ||||||
|         if (match_table_signature(PhysicalAddress((FlatPtr)rsdt_ptr->table_ptrs[i]), signature)) |         if (match_table_signature(PhysicalAddress((FlatPtr)rsdt->table_ptrs[i]), signature)) | ||||||
|             return PhysicalAddress((FlatPtr)rsdt_ptr->table_ptrs[i]); |             return PhysicalAddress((FlatPtr)rsdt->table_ptrs[i]); | ||||||
|     } |     } | ||||||
|     return {}; |     return {}; | ||||||
| } | } | ||||||
|  | 
 | ||||||
| } | } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -336,14 +336,12 @@ class DynamicParser; | ||||||
| class Parser; | class Parser; | ||||||
| 
 | 
 | ||||||
| namespace StaticParsing { | namespace StaticParsing { | ||||||
| PhysicalAddress search_rsdp_in_ebda(u16 ebda_segment); | PhysicalAddress find_rsdp(); | ||||||
| PhysicalAddress search_rsdp_in_bios_area(); |  | ||||||
| PhysicalAddress search_rsdp(); |  | ||||||
| bool match_table_signature(PhysicalAddress table_header, const char*); | bool match_table_signature(PhysicalAddress table_header, const char*); | ||||||
| PhysicalAddress search_table(PhysicalAddress rsdp, const char*); | PhysicalAddress search_table(PhysicalAddress rsdp, const char*); | ||||||
| PhysicalAddress search_table_in_xsdt(PhysicalAddress xsdt, const char*); | PhysicalAddress search_table_in_xsdt(PhysicalAddress xsdt, const char*); | ||||||
| PhysicalAddress search_table_in_rsdt(PhysicalAddress rsdt, const char*); | PhysicalAddress search_table_in_rsdt(PhysicalAddress rsdt, const char*); | ||||||
| inline bool validate_table(Structures::SDTHeader&, size_t length); | bool validate_table(const Structures::SDTHeader&, size_t length); | ||||||
| }; | }; | ||||||
| } | } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -53,7 +53,7 @@ void initialize() | ||||||
|     if (feature_level == FeatureLevel::Disabled) |     if (feature_level == FeatureLevel::Disabled) | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|     auto rsdp = StaticParsing::search_rsdp(); |     auto rsdp = StaticParsing::find_rsdp(); | ||||||
|     if (rsdp.is_null()) |     if (rsdp.is_null()) | ||||||
|         return; |         return; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -127,7 +127,7 @@ RefPtr<IRQController> InterruptManagement::get_responsible_irq_controller(u8 int | ||||||
| PhysicalAddress InterruptManagement::search_for_madt() | PhysicalAddress InterruptManagement::search_for_madt() | ||||||
| { | { | ||||||
|     dbg() << "Early access to ACPI tables for interrupt setup"; |     dbg() << "Early access to ACPI tables for interrupt setup"; | ||||||
|     auto rsdp = ACPI::StaticParsing::search_rsdp(); |     auto rsdp = ACPI::StaticParsing::find_rsdp(); | ||||||
|     if (rsdp.is_null()) |     if (rsdp.is_null()) | ||||||
|         return {}; |         return {}; | ||||||
|     return ACPI::StaticParsing::search_table(rsdp, "APIC"); |     return ACPI::StaticParsing::search_table(rsdp, "APIC"); | ||||||
|  |  | ||||||
							
								
								
									
										66
									
								
								Kernel/VM/TypedMapping.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								Kernel/VM/TypedMapping.h
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,66 @@ | ||||||
|  | /*
 | ||||||
|  |  * Copyright (c) 2020, Andreas Kling <kling@serenityos.org> | ||||||
|  |  * All rights reserved. | ||||||
|  |  * | ||||||
|  |  * Redistribution and use in source and binary forms, with or without | ||||||
|  |  * modification, are permitted provided that the following conditions are met: | ||||||
|  |  * | ||||||
|  |  * 1. Redistributions of source code must retain the above copyright notice, this | ||||||
|  |  *    list of conditions and the following disclaimer. | ||||||
|  |  * | ||||||
|  |  * 2. Redistributions in binary form must reproduce the above copyright notice, | ||||||
|  |  *    this list of conditions and the following disclaimer in the documentation | ||||||
|  |  *    and/or other materials provided with the distribution. | ||||||
|  |  * | ||||||
|  |  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||||||
|  |  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||||
|  |  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||||
|  |  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | ||||||
|  |  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||||
|  |  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | ||||||
|  |  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | ||||||
|  |  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | ||||||
|  |  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | ||||||
|  |  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||||
|  |  */ | ||||||
|  | 
 | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <AK/StringView.h> | ||||||
|  | #include <Kernel/VM/MemoryManager.h> | ||||||
|  | 
 | ||||||
|  | namespace Kernel { | ||||||
|  | 
 | ||||||
|  | template<typename T> | ||||||
|  | struct TypedMapping { | ||||||
|  |     const T* ptr() const { return reinterpret_cast<const T*>(region->vaddr().offset(offset).as_ptr()); } | ||||||
|  |     T* ptr() { return reinterpret_cast<T*>(region->vaddr().offset(offset).as_ptr()); } | ||||||
|  |     const T* operator->() const { return ptr(); } | ||||||
|  |     const T& operator*() const { return *ptr(); } | ||||||
|  |     T& operator*() { return *ptr(); } | ||||||
|  |     OwnPtr<Region> region; | ||||||
|  |     size_t offset { 0 }; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | template<typename T> | ||||||
|  | static TypedMapping<T> map_typed(PhysicalAddress paddr, size_t length, u8 access = Region::Access::Read) | ||||||
|  | { | ||||||
|  |     TypedMapping<T> table; | ||||||
|  |     table.region = MM.allocate_kernel_region(paddr.page_base(), PAGE_ROUND_UP(length), {}, access); | ||||||
|  |     table.offset = paddr.offset_in_page(); | ||||||
|  |     return table; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template<typename T> | ||||||
|  | static TypedMapping<T> map_typed(PhysicalAddress paddr) | ||||||
|  | { | ||||||
|  |     return map_typed<T>(paddr, sizeof(T)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | template<typename T> | ||||||
|  | static TypedMapping<T> map_typed_writable(PhysicalAddress paddr) | ||||||
|  | { | ||||||
|  |     return map_typed<T>(paddr, sizeof(T), Region::Access::Read | Region::Access::Write); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling