Kernel: Make ACPI load all SSDT headers after DSDT is loaded

This commit is contained in:
Bananymous 2024-04-10 15:03:54 +03:00
parent cdbdc1a822
commit 0ff68b7d66
6 changed files with 48 additions and 20 deletions

View File

@ -6,6 +6,6 @@
namespace Kernel::ACPI::AML
{
BAN::RefPtr<AML::Namespace> initialize_namespace(const SDTHeader& header);
BAN::RefPtr<AML::Namespace> initialize_namespace();
}

View File

@ -1,6 +1,7 @@
#pragma once
#include <kernel/ACPI/AML/Scope.h>
#include <kernel/ACPI/Headers.h>
#include <kernel/Lock/Mutex.h>
namespace Kernel::ACPI::AML
@ -14,7 +15,8 @@ namespace Kernel::ACPI::AML
Namespace(NameSeg name) : AML::Scope(Node::Type::Namespace, name) {}
static BAN::RefPtr<Namespace> parse(BAN::ConstByteSpan aml);
static BAN::RefPtr<AML::Namespace> create_root_namespace();
bool parse(const SDTHeader& header);
BAN::Optional<AML::NameString> resolve_path(const AML::NameString& relative_base, const AML::NameString& relative_path);

View File

@ -36,9 +36,7 @@ namespace Kernel::ACPI
return BAN::Error::from_errno(ENOMEM);
TRY(s_instance->initialize_impl());
auto dsdt = s_instance->get_header("DSDT", 0);
ASSERT(dsdt);
s_instance->m_namespace = AML::initialize_namespace(*dsdt);
s_instance->m_namespace = AML::initialize_namespace();
return {};
}

View File

@ -6,19 +6,34 @@
namespace Kernel::ACPI
{
BAN::RefPtr<AML::Namespace> AML::initialize_namespace(const SDTHeader& header)
BAN::RefPtr<AML::Namespace> AML::initialize_namespace()
{
dprintln("Parsing {}, {} bytes of AML", header, header.length);
auto ns = AML::Namespace::create_root_namespace();
auto aml_raw = BAN::ConstByteSpan { reinterpret_cast<const uint8_t*>(&header), header.length };
aml_raw = aml_raw.slice(sizeof(header));
auto ns = AML::Namespace::parse(aml_raw);
if (!ns)
// Parse DSDT
auto* dsdt = ACPI::ACPI::get().get_header("DSDT", 0);
if (!dsdt)
{
dwarnln("Failed to parse ACPI namespace");
dwarnln("Failed to get DSDT");
return {};
}
if (!ns->parse(*dsdt))
{
dwarnln("Failed to parse DSDT");
return {};
}
for (uint32_t i = 0;; i++)
{
auto* ssdt = ACPI::ACPI::get().get_header("SSDT", i);
if (!ssdt)
break;
if (!ns->parse(*ssdt))
{
dwarnln("Failed to parse SSDT");
return {};
}
}
#if AML_DEBUG_LEVEL >= 1
ns->debug_print(0);

View File

@ -191,13 +191,13 @@ namespace Kernel::ACPI
return true;
}
BAN::RefPtr<AML::Namespace> AML::Namespace::parse(BAN::ConstByteSpan aml_data)
BAN::RefPtr<AML::Namespace> AML::Namespace::create_root_namespace()
{
ASSERT(!s_root_namespace);
s_root_namespace = MUST(BAN::RefPtr<Namespace>::create(NameSeg("\\"sv)));
AML::ParseContext context;
context.scope = AML::NameString("\\"sv);
context.aml_data = aml_data;
// Add predefined namespaces
#define ADD_PREDEFIED_NAMESPACE(NAME) \
@ -209,17 +209,30 @@ namespace Kernel::ACPI
ADD_PREDEFIED_NAMESPACE("_TZ"sv);
#undef ADD_PREDEFIED_NAMESPACE
return s_root_namespace;
}
bool AML::Namespace::parse(const SDTHeader& header)
{
ASSERT(this == s_root_namespace.ptr());
dprintln("Parsing {}, {} bytes of AML", header, header.length);
AML::ParseContext context;
context.scope = AML::NameString("\\"sv);
context.aml_data = BAN::ConstByteSpan(reinterpret_cast<const uint8_t*>(&header), header.length).slice(sizeof(header));
while (context.aml_data.size() > 0)
{
auto result = AML::parse_object(context);
if (!result.success())
{
AML_ERROR("Failed to parse object");
return {};
return false;
}
}
return s_root_namespace;
return true;
}
}

View File

@ -154,9 +154,6 @@ extern "C" void kernel_main(uint32_t boot_magic, uint32_t boot_info)
dprintln("Virtual TTY initialized");
}
if (ACPI::ACPI::get().enter_acpi_mode(InterruptController::get().is_using_apic()).is_error())
dprintln("Failed to enter ACPI mode");
Random::initialize();
dprintln("RNG initialized");
@ -181,6 +178,9 @@ static void init2(void*)
ASSERT(console->is_tty());
((TTY*)console.ptr())->set_as_current();
if (ACPI::ACPI::get().enter_acpi_mode(InterruptController::get().is_using_apic()).is_error())
dprintln("Failed to enter ACPI mode");
DevFileSystem::get().initialize_device_updater();
#if 0