mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 16:52:43 +00:00 
			
		
		
		
	Kernel: Simplify scanning BIOS/EBDA and MP parser initialization
Add a MappedROM::find_chunk_starting_with() helper since that's a very common usage pattern in clients of this code. Also convert MultiProcessorParser from a persistent singleton object to a temporary object constructed via a failable factory function.
This commit is contained in:
		
							parent
							
								
									84b7bc5e14
								
							
						
					
					
						commit
						4b847810bf
					
				
					 8 changed files with 47 additions and 101 deletions
				
			
		|  | @ -336,8 +336,10 @@ class DynamicParser; | |||
| class Parser; | ||||
| 
 | ||||
| namespace StaticParsing { | ||||
| PhysicalAddress find_rsdp(); | ||||
| Optional<PhysicalAddress> find_rsdp(); | ||||
| PhysicalAddress find_table(PhysicalAddress rsdp, const StringView& signature); | ||||
| }; | ||||
| } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -54,13 +54,13 @@ void initialize() | |||
|         return; | ||||
| 
 | ||||
|     auto rsdp = StaticParsing::find_rsdp(); | ||||
|     if (rsdp.is_null()) | ||||
|     if (!rsdp.has_value()) | ||||
|         return; | ||||
| 
 | ||||
|     if (feature_level == FeatureLevel::Enabled) | ||||
|         Parser::initialize<DynamicParser>(rsdp); | ||||
|         Parser::initialize<DynamicParser>(rsdp.value()); | ||||
|     else | ||||
|         Parser::initialize<Parser>(rsdp); | ||||
|         Parser::initialize<Parser>(rsdp.value()); | ||||
| } | ||||
| 
 | ||||
| bool is_enabled() | ||||
|  |  | |||
|  | @ -37,29 +37,20 @@ | |||
| 
 | ||||
| namespace Kernel { | ||||
| 
 | ||||
| static MultiProcessorParser* s_parser; | ||||
| 
 | ||||
| bool MultiProcessorParser::is_initialized() | ||||
| OwnPtr<MultiProcessorParser> MultiProcessorParser::autodetect() | ||||
| { | ||||
|     return s_parser != nullptr; | ||||
|     auto floating_pointer = find_floating_pointer(); | ||||
|     if (!floating_pointer.has_value()) | ||||
|         return nullptr; | ||||
|     return adopt_own(*new MultiProcessorParser(floating_pointer.value())); | ||||
| } | ||||
| 
 | ||||
| void MultiProcessorParser::initialize() | ||||
| MultiProcessorParser::MultiProcessorParser(PhysicalAddress floating_pointer) | ||||
|     : m_floating_pointer(floating_pointer) | ||||
| { | ||||
|     ASSERT(!is_initialized()); | ||||
|     s_parser = new MultiProcessorParser; | ||||
| } | ||||
| 
 | ||||
| MultiProcessorParser::MultiProcessorParser() | ||||
|     : m_floating_pointer(search_floating_pointer()) | ||||
| { | ||||
|     if (!m_floating_pointer.is_null()) { | ||||
|         klog() << "MultiProcessor: Floating Pointer Structure @ " << PhysicalAddress(m_floating_pointer); | ||||
|         parse_floating_pointer_data(); | ||||
|         parse_configuration_table(); | ||||
|     } else { | ||||
|         klog() << "MultiProcessor: Can't Locate Floating Pointer Structure, disabled."; | ||||
|     } | ||||
|     klog() << "MultiProcessor: Floating Pointer Structure @ " << m_floating_pointer; | ||||
|     parse_floating_pointer_data(); | ||||
|     parse_configuration_table(); | ||||
| } | ||||
| 
 | ||||
| void MultiProcessorParser::parse_floating_pointer_data() | ||||
|  | @ -114,32 +105,13 @@ void MultiProcessorParser::parse_configuration_table() | |||
|     } | ||||
| } | ||||
| 
 | ||||
| PhysicalAddress MultiProcessorParser::search_floating_pointer() | ||||
| Optional<PhysicalAddress> MultiProcessorParser::find_floating_pointer() | ||||
| { | ||||
|     auto mp_floating_pointer = search_floating_pointer_in_ebda(); | ||||
|     if (!mp_floating_pointer.is_null()) | ||||
|     StringView signature("_MP_"); | ||||
|     auto mp_floating_pointer = map_ebda().find_chunk_starting_with(signature, 16); | ||||
|     if (mp_floating_pointer.has_value()) | ||||
|         return mp_floating_pointer; | ||||
|     return search_floating_pointer_in_bios_area(); | ||||
| } | ||||
| 
 | ||||
| PhysicalAddress MultiProcessorParser::search_floating_pointer_in_ebda() | ||||
| { | ||||
|     klog() << "MultiProcessor: Probing EBDA"; | ||||
|     auto ebda = map_ebda(); | ||||
|     for (auto* floating_pointer_str = ebda.base(); floating_pointer_str < ebda.end(); floating_pointer_str += 16) { | ||||
|         if (!strncmp("_MP_", (const char*)floating_pointer_str, strlen("_MP_"))) | ||||
|             return ebda.paddr_of(floating_pointer_str); | ||||
|     } | ||||
|     return {}; | ||||
| } | ||||
| PhysicalAddress MultiProcessorParser::search_floating_pointer_in_bios_area() | ||||
| { | ||||
|     auto bios = map_bios(); | ||||
|     for (auto* floating_pointer_str = bios.base(); floating_pointer_str < bios.end(); floating_pointer_str += 16) { | ||||
|         if (!strncmp("_MP_", (const char*)floating_pointer_str, strlen("_MP_"))) | ||||
|             return bios.paddr_of(floating_pointer_str); | ||||
|     } | ||||
|     return {}; | ||||
|     return map_bios().find_chunk_starting_with(signature, 16); | ||||
| } | ||||
| 
 | ||||
| Vector<u8> MultiProcessorParser::get_pci_bus_ids() const | ||||
|  | @ -152,12 +124,6 @@ Vector<u8> MultiProcessorParser::get_pci_bus_ids() const | |||
|     return pci_bus_ids; | ||||
| } | ||||
| 
 | ||||
| MultiProcessorParser& MultiProcessorParser::the() | ||||
| { | ||||
|     ASSERT(is_initialized()); | ||||
|     return *s_parser; | ||||
| } | ||||
| 
 | ||||
| Vector<PCIInterruptOverrideMetadata> MultiProcessorParser::get_pci_interrupt_redirections() | ||||
| { | ||||
|     dbg() << "MultiProcessor: Get PCI IOAPIC redirections"; | ||||
|  |  | |||
|  | @ -189,25 +189,21 @@ struct [[gnu::packed]] CompatibilityBusAddressSpaceModifierEntry | |||
| 
 | ||||
| class PCIInterruptOverrideMetadata; | ||||
| 
 | ||||
| class MultiProcessorParser { | ||||
| class MultiProcessorParser final { | ||||
| public: | ||||
|     static MultiProcessorParser& the(); | ||||
|     static OwnPtr<MultiProcessorParser> autodetect(); | ||||
| 
 | ||||
|     static bool is_initialized(); | ||||
|     static void initialize(); | ||||
|     Vector<PCIInterruptOverrideMetadata> get_pci_interrupt_redirections(); | ||||
| 
 | ||||
| protected: | ||||
|     MultiProcessorParser(); | ||||
| private: | ||||
|     explicit MultiProcessorParser(PhysicalAddress floating_pointer); | ||||
| 
 | ||||
|     void parse_configuration_table(); | ||||
|     void parse_floating_pointer_data(); | ||||
| 
 | ||||
|     Vector<u8> get_pci_bus_ids() const; | ||||
| 
 | ||||
|     PhysicalAddress search_floating_pointer(); | ||||
|     PhysicalAddress search_floating_pointer_in_ebda(); | ||||
|     PhysicalAddress search_floating_pointer_in_bios_area(); | ||||
|     static Optional<PhysicalAddress> find_floating_pointer(); | ||||
| 
 | ||||
|     PhysicalAddress m_floating_pointer; | ||||
|     PhysicalAddress m_configuration_table; | ||||
|  |  | |||
|  | @ -322,29 +322,6 @@ Parser::Parser(PhysicalAddress rsdp) | |||
|     locate_static_data(); | ||||
| } | ||||
| 
 | ||||
| static PhysicalAddress find_rsdp_in_ebda() | ||||
| { | ||||
|     auto ebda = map_ebda(); | ||||
|     for (auto* rsdp_str = ebda.base(); rsdp_str < ebda.end(); rsdp_str += 16) { | ||||
| #ifdef ACPI_DEBUG | ||||
|         dbg() << "ACPI: Looking for RSDP in EBDA @ V " << (void*)rsdp_str << ", P " << (void*)p_rsdp_str; | ||||
| #endif | ||||
|         if (!strncmp("RSD PTR ", (const char*)rsdp_str, strlen("RSD PTR "))) | ||||
|             return ebda.paddr_of(rsdp_str); | ||||
|     } | ||||
|     return {}; | ||||
| } | ||||
| 
 | ||||
| static PhysicalAddress find_rsdp_in_bios_area() | ||||
| { | ||||
|     auto bios = map_bios(); | ||||
|     for (auto* rsdp_str = bios.base(); rsdp_str < bios.end(); rsdp_str += 16) { | ||||
|         if (!strncmp("RSD PTR ", (const char*)rsdp_str, strlen("RSD PTR "))) | ||||
|             return bios.paddr_of(rsdp_str); | ||||
|     } | ||||
|     return {}; | ||||
| } | ||||
| 
 | ||||
| static bool validate_table(const Structures::SDTHeader& v_header, size_t length) | ||||
| { | ||||
|     u8 checksum = 0; | ||||
|  | @ -356,13 +333,13 @@ static bool validate_table(const Structures::SDTHeader& v_header, size_t length) | |||
|     return false; | ||||
| } | ||||
| 
 | ||||
| PhysicalAddress StaticParsing::find_rsdp() | ||||
| Optional<PhysicalAddress> StaticParsing::find_rsdp() | ||||
| { | ||||
|     klog() << "ACPI: Probing EBDA"; | ||||
|     auto rsdp = find_rsdp_in_ebda(); | ||||
|     if (!rsdp.is_null()) | ||||
|     StringView signature("RSD PTR "); | ||||
|     auto rsdp = map_ebda().find_chunk_starting_with(signature, 16); | ||||
|     if (rsdp.has_value()) | ||||
|         return rsdp; | ||||
|     return find_rsdp_in_bios_area(); | ||||
|     return map_bios().find_chunk_starting_with(signature, 16); | ||||
| } | ||||
| 
 | ||||
| PhysicalAddress StaticParsing::find_table(PhysicalAddress rsdp_address, const StringView& signature) | ||||
|  |  | |||
|  | @ -129,9 +129,9 @@ PhysicalAddress InterruptManagement::search_for_madt() | |||
| { | ||||
|     dbg() << "Early access to ACPI tables for interrupt setup"; | ||||
|     auto rsdp = ACPI::StaticParsing::find_rsdp(); | ||||
|     if (rsdp.is_null()) | ||||
|     if (!rsdp.has_value()) | ||||
|         return {}; | ||||
|     return ACPI::StaticParsing::find_table(rsdp, "APIC"); | ||||
|     return ACPI::StaticParsing::find_table(rsdp.value(), "APIC"); | ||||
| } | ||||
| 
 | ||||
| InterruptManagement::InterruptManagement() | ||||
|  | @ -189,8 +189,10 @@ void InterruptManagement::switch_to_ioapic_mode() | |||
|     } | ||||
|     APIC::init(); | ||||
|     APIC::enable_bsp(); | ||||
|     MultiProcessorParser::initialize(); | ||||
|     locate_pci_interrupt_overrides(); | ||||
| 
 | ||||
|     if (auto mp_parser = MultiProcessorParser::autodetect()) { | ||||
|         m_pci_interrupt_overrides = mp_parser->get_pci_interrupt_redirections(); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void InterruptManagement::locate_apic_data() | ||||
|  | @ -231,9 +233,4 @@ void InterruptManagement::locate_apic_data() | |||
|     } | ||||
| } | ||||
| 
 | ||||
| void InterruptManagement::locate_pci_interrupt_overrides() | ||||
| { | ||||
|     m_pci_interrupt_overrides = MultiProcessorParser::the().get_pci_interrupt_redirections(); | ||||
| } | ||||
| 
 | ||||
| } | ||||
|  |  | |||
|  | @ -88,7 +88,6 @@ private: | |||
|     InterruptManagement(); | ||||
|     PhysicalAddress search_for_madt(); | ||||
|     void locate_apic_data(); | ||||
|     void locate_pci_interrupt_overrides(); | ||||
|     bool m_smp_enabled { false }; | ||||
|     FixedArray<RefPtr<IRQController>> m_interrupt_controllers { 1 }; | ||||
|     Vector<ISAInterruptOverrideMetadata> m_isa_interrupt_overrides; | ||||
|  |  | |||
|  | @ -39,6 +39,15 @@ struct MappedROM { | |||
|     size_t offset { 0 }; | ||||
|     PhysicalAddress paddr; | ||||
| 
 | ||||
|     Optional<PhysicalAddress> find_chunk_starting_with(StringView prefix, size_t chunk_size) const | ||||
|     { | ||||
|         for (auto* candidate = base(); candidate < end(); candidate += chunk_size) { | ||||
|             if (!__builtin_memcmp(prefix.characters_without_null_termination(), candidate, prefix.length())) | ||||
|                 return paddr_of(candidate); | ||||
|         } | ||||
|         return {}; | ||||
|     } | ||||
| 
 | ||||
|     PhysicalAddress paddr_of(const u8* ptr) const { return paddr.offset(ptr - this->base()); } | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Andreas Kling
						Andreas Kling