mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 01:48:11 +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;
|
class Parser;
|
||||||
|
|
||||||
namespace StaticParsing {
|
namespace StaticParsing {
|
||||||
PhysicalAddress find_rsdp();
|
Optional<PhysicalAddress> find_rsdp();
|
||||||
PhysicalAddress find_table(PhysicalAddress rsdp, const StringView& signature);
|
PhysicalAddress find_table(PhysicalAddress rsdp, const StringView& signature);
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,13 +54,13 @@ void initialize()
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto rsdp = StaticParsing::find_rsdp();
|
auto rsdp = StaticParsing::find_rsdp();
|
||||||
if (rsdp.is_null())
|
if (!rsdp.has_value())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (feature_level == FeatureLevel::Enabled)
|
if (feature_level == FeatureLevel::Enabled)
|
||||||
Parser::initialize<DynamicParser>(rsdp);
|
Parser::initialize<DynamicParser>(rsdp.value());
|
||||||
else
|
else
|
||||||
Parser::initialize<Parser>(rsdp);
|
Parser::initialize<Parser>(rsdp.value());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool is_enabled()
|
bool is_enabled()
|
||||||
|
|
|
@ -37,29 +37,20 @@
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
static MultiProcessorParser* s_parser;
|
OwnPtr<MultiProcessorParser> MultiProcessorParser::autodetect()
|
||||||
|
|
||||||
bool MultiProcessorParser::is_initialized()
|
|
||||||
{
|
{
|
||||||
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());
|
klog() << "MultiProcessor: Floating Pointer Structure @ " << m_floating_pointer;
|
||||||
s_parser = new MultiProcessorParser;
|
parse_floating_pointer_data();
|
||||||
}
|
parse_configuration_table();
|
||||||
|
|
||||||
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.";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MultiProcessorParser::parse_floating_pointer_data()
|
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();
|
StringView signature("_MP_");
|
||||||
if (!mp_floating_pointer.is_null())
|
auto mp_floating_pointer = map_ebda().find_chunk_starting_with(signature, 16);
|
||||||
|
if (mp_floating_pointer.has_value())
|
||||||
return mp_floating_pointer;
|
return mp_floating_pointer;
|
||||||
return search_floating_pointer_in_bios_area();
|
return map_bios().find_chunk_starting_with(signature, 16);
|
||||||
}
|
|
||||||
|
|
||||||
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 {};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<u8> MultiProcessorParser::get_pci_bus_ids() const
|
Vector<u8> MultiProcessorParser::get_pci_bus_ids() const
|
||||||
|
@ -152,12 +124,6 @@ Vector<u8> MultiProcessorParser::get_pci_bus_ids() const
|
||||||
return pci_bus_ids;
|
return pci_bus_ids;
|
||||||
}
|
}
|
||||||
|
|
||||||
MultiProcessorParser& MultiProcessorParser::the()
|
|
||||||
{
|
|
||||||
ASSERT(is_initialized());
|
|
||||||
return *s_parser;
|
|
||||||
}
|
|
||||||
|
|
||||||
Vector<PCIInterruptOverrideMetadata> MultiProcessorParser::get_pci_interrupt_redirections()
|
Vector<PCIInterruptOverrideMetadata> MultiProcessorParser::get_pci_interrupt_redirections()
|
||||||
{
|
{
|
||||||
dbg() << "MultiProcessor: Get PCI IOAPIC redirections";
|
dbg() << "MultiProcessor: Get PCI IOAPIC redirections";
|
||||||
|
|
|
@ -189,25 +189,21 @@ struct [[gnu::packed]] CompatibilityBusAddressSpaceModifierEntry
|
||||||
|
|
||||||
class PCIInterruptOverrideMetadata;
|
class PCIInterruptOverrideMetadata;
|
||||||
|
|
||||||
class MultiProcessorParser {
|
class MultiProcessorParser final {
|
||||||
public:
|
public:
|
||||||
static MultiProcessorParser& the();
|
static OwnPtr<MultiProcessorParser> autodetect();
|
||||||
|
|
||||||
static bool is_initialized();
|
|
||||||
static void initialize();
|
|
||||||
Vector<PCIInterruptOverrideMetadata> get_pci_interrupt_redirections();
|
Vector<PCIInterruptOverrideMetadata> get_pci_interrupt_redirections();
|
||||||
|
|
||||||
protected:
|
private:
|
||||||
MultiProcessorParser();
|
explicit MultiProcessorParser(PhysicalAddress floating_pointer);
|
||||||
|
|
||||||
void parse_configuration_table();
|
void parse_configuration_table();
|
||||||
void parse_floating_pointer_data();
|
void parse_floating_pointer_data();
|
||||||
|
|
||||||
Vector<u8> get_pci_bus_ids() const;
|
Vector<u8> get_pci_bus_ids() const;
|
||||||
|
|
||||||
PhysicalAddress search_floating_pointer();
|
static Optional<PhysicalAddress> find_floating_pointer();
|
||||||
PhysicalAddress search_floating_pointer_in_ebda();
|
|
||||||
PhysicalAddress search_floating_pointer_in_bios_area();
|
|
||||||
|
|
||||||
PhysicalAddress m_floating_pointer;
|
PhysicalAddress m_floating_pointer;
|
||||||
PhysicalAddress m_configuration_table;
|
PhysicalAddress m_configuration_table;
|
||||||
|
|
|
@ -322,29 +322,6 @@ Parser::Parser(PhysicalAddress rsdp)
|
||||||
locate_static_data();
|
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)
|
static bool validate_table(const Structures::SDTHeader& v_header, size_t length)
|
||||||
{
|
{
|
||||||
u8 checksum = 0;
|
u8 checksum = 0;
|
||||||
|
@ -356,13 +333,13 @@ static bool validate_table(const Structures::SDTHeader& v_header, size_t length)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicalAddress StaticParsing::find_rsdp()
|
Optional<PhysicalAddress> StaticParsing::find_rsdp()
|
||||||
{
|
{
|
||||||
klog() << "ACPI: Probing EBDA";
|
StringView signature("RSD PTR ");
|
||||||
auto rsdp = find_rsdp_in_ebda();
|
auto rsdp = map_ebda().find_chunk_starting_with(signature, 16);
|
||||||
if (!rsdp.is_null())
|
if (rsdp.has_value())
|
||||||
return rsdp;
|
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)
|
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";
|
dbg() << "Early access to ACPI tables for interrupt setup";
|
||||||
auto rsdp = ACPI::StaticParsing::find_rsdp();
|
auto rsdp = ACPI::StaticParsing::find_rsdp();
|
||||||
if (rsdp.is_null())
|
if (!rsdp.has_value())
|
||||||
return {};
|
return {};
|
||||||
return ACPI::StaticParsing::find_table(rsdp, "APIC");
|
return ACPI::StaticParsing::find_table(rsdp.value(), "APIC");
|
||||||
}
|
}
|
||||||
|
|
||||||
InterruptManagement::InterruptManagement()
|
InterruptManagement::InterruptManagement()
|
||||||
|
@ -189,8 +189,10 @@ void InterruptManagement::switch_to_ioapic_mode()
|
||||||
}
|
}
|
||||||
APIC::init();
|
APIC::init();
|
||||||
APIC::enable_bsp();
|
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()
|
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();
|
InterruptManagement();
|
||||||
PhysicalAddress search_for_madt();
|
PhysicalAddress search_for_madt();
|
||||||
void locate_apic_data();
|
void locate_apic_data();
|
||||||
void locate_pci_interrupt_overrides();
|
|
||||||
bool m_smp_enabled { false };
|
bool m_smp_enabled { false };
|
||||||
FixedArray<RefPtr<IRQController>> m_interrupt_controllers { 1 };
|
FixedArray<RefPtr<IRQController>> m_interrupt_controllers { 1 };
|
||||||
Vector<ISAInterruptOverrideMetadata> m_isa_interrupt_overrides;
|
Vector<ISAInterruptOverrideMetadata> m_isa_interrupt_overrides;
|
||||||
|
|
|
@ -39,6 +39,15 @@ struct MappedROM {
|
||||||
size_t offset { 0 };
|
size_t offset { 0 };
|
||||||
PhysicalAddress paddr;
|
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()); }
|
PhysicalAddress paddr_of(const u8* ptr) const { return paddr.offset(ptr - this->base()); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue