mirror of
https://github.com/SerenityOS/serenity
synced 2024-10-15 04:13:11 +00:00
Kernel: Run clang-format on files
Let's rip off the band-aid
This commit is contained in:
parent
d0629d0a8c
commit
81adefef27
|
@ -29,70 +29,70 @@
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
namespace ACPI {
|
namespace ACPI {
|
||||||
void DynamicParser::initialize(PhysicalAddress rsdp)
|
void DynamicParser::initialize(PhysicalAddress rsdp)
|
||||||
{
|
{
|
||||||
if (!StaticParser::is_initialized()) {
|
if (!StaticParser::is_initialized()) {
|
||||||
new DynamicParser(rsdp);
|
new DynamicParser(rsdp);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
void DynamicParser::initialize_without_rsdp()
|
}
|
||||||
{
|
void DynamicParser::initialize_without_rsdp()
|
||||||
if (!StaticParser::is_initialized()) {
|
{
|
||||||
new DynamicParser();
|
if (!StaticParser::is_initialized()) {
|
||||||
}
|
new DynamicParser();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
DynamicParser::DynamicParser()
|
DynamicParser::DynamicParser()
|
||||||
: IRQHandler(9)
|
: IRQHandler(9)
|
||||||
, StaticParser()
|
, StaticParser()
|
||||||
|
|
||||||
{
|
{
|
||||||
klog() << "ACPI: Dynamic Parsing Enabled, Can parse AML";
|
klog() << "ACPI: Dynamic Parsing Enabled, Can parse AML";
|
||||||
}
|
}
|
||||||
DynamicParser::DynamicParser(PhysicalAddress rsdp)
|
DynamicParser::DynamicParser(PhysicalAddress rsdp)
|
||||||
: IRQHandler(9)
|
: IRQHandler(9)
|
||||||
, StaticParser(rsdp)
|
, StaticParser(rsdp)
|
||||||
{
|
{
|
||||||
klog() << "ACPI: Dynamic Parsing Enabled, Can parse AML";
|
klog() << "ACPI: Dynamic Parsing Enabled, Can parse AML";
|
||||||
}
|
}
|
||||||
|
|
||||||
void DynamicParser::handle_irq(const RegisterState&)
|
void DynamicParser::handle_irq(const RegisterState&)
|
||||||
{
|
{
|
||||||
// FIXME: Implement IRQ handling of ACPI signals!
|
// FIXME: Implement IRQ handling of ACPI signals!
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DynamicParser::enable_aml_interpretation()
|
void DynamicParser::enable_aml_interpretation()
|
||||||
{
|
{
|
||||||
// FIXME: Implement AML Interpretation
|
// FIXME: Implement AML Interpretation
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
void DynamicParser::enable_aml_interpretation(File&)
|
void DynamicParser::enable_aml_interpretation(File&)
|
||||||
{
|
{
|
||||||
// FIXME: Implement AML Interpretation
|
// FIXME: Implement AML Interpretation
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
void DynamicParser::enable_aml_interpretation(u8*, u32)
|
void DynamicParser::enable_aml_interpretation(u8*, u32)
|
||||||
{
|
{
|
||||||
// FIXME: Implement AML Interpretation
|
// FIXME: Implement AML Interpretation
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
void DynamicParser::disable_aml_interpretation()
|
void DynamicParser::disable_aml_interpretation()
|
||||||
{
|
{
|
||||||
// FIXME: Implement AML Interpretation
|
// FIXME: Implement AML Interpretation
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
void DynamicParser::try_acpi_shutdown()
|
void DynamicParser::try_acpi_shutdown()
|
||||||
{
|
{
|
||||||
// FIXME: Implement AML Interpretation to perform ACPI shutdown
|
// FIXME: Implement AML Interpretation to perform ACPI shutdown
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DynamicParser::build_namespace()
|
void DynamicParser::build_namespace()
|
||||||
{
|
{
|
||||||
// FIXME: Implement AML Interpretation to build the ACPI namespace
|
// FIXME: Implement AML Interpretation to build the ACPI namespace
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,30 +35,30 @@
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
namespace ACPI {
|
namespace ACPI {
|
||||||
class DynamicParser final : public IRQHandler
|
class DynamicParser final : public IRQHandler
|
||||||
, StaticParser {
|
, StaticParser {
|
||||||
public:
|
public:
|
||||||
static void initialize(PhysicalAddress rsdp);
|
static void initialize(PhysicalAddress rsdp);
|
||||||
static void initialize_without_rsdp();
|
static void initialize_without_rsdp();
|
||||||
|
|
||||||
virtual void enable_aml_interpretation() override;
|
virtual void enable_aml_interpretation() override;
|
||||||
virtual void enable_aml_interpretation(File& dsdt_file) override;
|
virtual void enable_aml_interpretation(File& dsdt_file) override;
|
||||||
virtual void enable_aml_interpretation(u8* physical_dsdt, u32 dsdt_payload_legnth) override;
|
virtual void enable_aml_interpretation(u8* physical_dsdt, u32 dsdt_payload_legnth) override;
|
||||||
virtual void disable_aml_interpretation() override;
|
virtual void disable_aml_interpretation() override;
|
||||||
virtual void try_acpi_shutdown() override;
|
virtual void try_acpi_shutdown() override;
|
||||||
virtual bool can_shutdown() override { return true; }
|
virtual bool can_shutdown() override { return true; }
|
||||||
virtual const char* purpose() const override { return "ACPI Parser"; }
|
virtual const char* purpose() const override { return "ACPI Parser"; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
DynamicParser();
|
DynamicParser();
|
||||||
explicit DynamicParser(PhysicalAddress);
|
explicit DynamicParser(PhysicalAddress);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void build_namespace();
|
void build_namespace();
|
||||||
// ^IRQHandler
|
// ^IRQHandler
|
||||||
virtual void handle_irq(const RegisterState&) override;
|
virtual void handle_irq(const RegisterState&) override;
|
||||||
|
|
||||||
OwnPtr<Region> m_acpi_namespace;
|
OwnPtr<Region> m_acpi_namespace;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,85 +28,85 @@
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
namespace ACPI {
|
namespace ACPI {
|
||||||
static Parser* s_acpi_parser;
|
static Parser* s_acpi_parser;
|
||||||
|
|
||||||
Parser& Parser::the()
|
Parser& Parser::the()
|
||||||
{
|
{
|
||||||
ASSERT(s_acpi_parser != nullptr);
|
ASSERT(s_acpi_parser != nullptr);
|
||||||
return *s_acpi_parser;
|
return *s_acpi_parser;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Parser::initialize_limited()
|
void Parser::initialize_limited()
|
||||||
{
|
{
|
||||||
if (!Parser::is_initialized()) {
|
if (!Parser::is_initialized()) {
|
||||||
s_acpi_parser = new Parser(false);
|
s_acpi_parser = new Parser(false);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool Parser::is_initialized()
|
|
||||||
{
|
|
||||||
return (s_acpi_parser != nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
Parser::Parser(bool usable)
|
|
||||||
{
|
|
||||||
if (usable) {
|
|
||||||
klog() << "ACPI: Setting up a functional parser";
|
|
||||||
} else {
|
|
||||||
klog() << "ACPI: Limited Initialization. Vital functions are disabled by a request";
|
|
||||||
}
|
|
||||||
s_acpi_parser = this;
|
|
||||||
}
|
|
||||||
|
|
||||||
PhysicalAddress Parser::find_table(const char*)
|
|
||||||
{
|
|
||||||
klog() << "ACPI: Requested to search for a table, Abort!";
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
void Parser::try_acpi_reboot()
|
|
||||||
{
|
|
||||||
klog() << "ACPI: Cannot invoke reboot!";
|
|
||||||
}
|
|
||||||
|
|
||||||
void Parser::try_acpi_shutdown()
|
|
||||||
{
|
|
||||||
klog() << "ACPI: Cannot invoke shutdown!";
|
|
||||||
}
|
|
||||||
|
|
||||||
void Parser::enable_aml_interpretation()
|
|
||||||
{
|
|
||||||
klog() << "ACPI: No AML Interpretation Allowed";
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
}
|
|
||||||
void Parser::enable_aml_interpretation(File&)
|
|
||||||
{
|
|
||||||
klog() << "ACPI: No AML Interpretation Allowed";
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
}
|
|
||||||
void Parser::enable_aml_interpretation(u8*, u32)
|
|
||||||
{
|
|
||||||
klog() << "ACPI: No AML Interpretation Allowed";
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
}
|
|
||||||
void Parser::disable_aml_interpretation()
|
|
||||||
{
|
|
||||||
klog() << "ACPI Limited: No AML Interpretation Allowed";
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
}
|
|
||||||
const FADTFlags::HardwareFeatures& Parser::hardware_features() const
|
|
||||||
{
|
|
||||||
klog() << "ACPI Limited: Hardware features cannot be obtained";
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
}
|
|
||||||
const FADTFlags::x86_Specific_Flags& Parser::x86_specific_flags() const
|
|
||||||
{
|
|
||||||
klog() << "ACPI Limited: x86 specific features cannot be obtained";
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
}
|
|
||||||
bool Parser::is_operable()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Parser::is_initialized()
|
||||||
|
{
|
||||||
|
return (s_acpi_parser != nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
Parser::Parser(bool usable)
|
||||||
|
{
|
||||||
|
if (usable) {
|
||||||
|
klog() << "ACPI: Setting up a functional parser";
|
||||||
|
} else {
|
||||||
|
klog() << "ACPI: Limited Initialization. Vital functions are disabled by a request";
|
||||||
|
}
|
||||||
|
s_acpi_parser = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
PhysicalAddress Parser::find_table(const char*)
|
||||||
|
{
|
||||||
|
klog() << "ACPI: Requested to search for a table, Abort!";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void Parser::try_acpi_reboot()
|
||||||
|
{
|
||||||
|
klog() << "ACPI: Cannot invoke reboot!";
|
||||||
|
}
|
||||||
|
|
||||||
|
void Parser::try_acpi_shutdown()
|
||||||
|
{
|
||||||
|
klog() << "ACPI: Cannot invoke shutdown!";
|
||||||
|
}
|
||||||
|
|
||||||
|
void Parser::enable_aml_interpretation()
|
||||||
|
{
|
||||||
|
klog() << "ACPI: No AML Interpretation Allowed";
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
void Parser::enable_aml_interpretation(File&)
|
||||||
|
{
|
||||||
|
klog() << "ACPI: No AML Interpretation Allowed";
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
void Parser::enable_aml_interpretation(u8*, u32)
|
||||||
|
{
|
||||||
|
klog() << "ACPI: No AML Interpretation Allowed";
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
void Parser::disable_aml_interpretation()
|
||||||
|
{
|
||||||
|
klog() << "ACPI Limited: No AML Interpretation Allowed";
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
const FADTFlags::HardwareFeatures& Parser::hardware_features() const
|
||||||
|
{
|
||||||
|
klog() << "ACPI Limited: Hardware features cannot be obtained";
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
const FADTFlags::x86_Specific_Flags& Parser::x86_specific_flags() const
|
||||||
|
{
|
||||||
|
klog() << "ACPI Limited: x86 specific features cannot be obtained";
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
bool Parser::is_operable()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,448 +35,448 @@
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
namespace ACPI {
|
namespace ACPI {
|
||||||
|
|
||||||
void StaticParser::initialize(PhysicalAddress rsdp)
|
void StaticParser::initialize(PhysicalAddress rsdp)
|
||||||
{
|
{
|
||||||
if (!Parser::is_initialized()) {
|
if (!Parser::is_initialized()) {
|
||||||
new StaticParser(rsdp);
|
new StaticParser(rsdp);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
void StaticParser::initialize_without_rsdp()
|
}
|
||||||
{
|
void StaticParser::initialize_without_rsdp()
|
||||||
if (!Parser::is_initialized()) {
|
{
|
||||||
new StaticParser();
|
if (!Parser::is_initialized()) {
|
||||||
}
|
new StaticParser();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool StaticParser::is_initialized()
|
bool StaticParser::is_initialized()
|
||||||
{
|
{
|
||||||
return Parser::is_initialized();
|
return Parser::is_initialized();
|
||||||
}
|
}
|
||||||
|
|
||||||
void StaticParser::locate_static_data()
|
void StaticParser::locate_static_data()
|
||||||
{
|
{
|
||||||
locate_main_system_description_table();
|
locate_main_system_description_table();
|
||||||
initialize_main_system_description_table();
|
initialize_main_system_description_table();
|
||||||
init_fadt();
|
init_fadt();
|
||||||
init_facs();
|
init_facs();
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicalAddress StaticParser::find_table(const char* sig)
|
PhysicalAddress StaticParser::find_table(const char* sig)
|
||||||
{
|
{
|
||||||
#ifdef ACPI_DEBUG
|
#ifdef ACPI_DEBUG
|
||||||
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 region = MM.allocate_kernel_region(p_sdt.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser Tables Finding", Region::Access::Read);
|
||||||
auto* sdt = (const Structures::SDTHeader*)region->vaddr().offset(p_sdt.offset_in_page()).as_ptr();
|
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 " << physical_sdt_ptr;
|
dbg() << "ACPI: Examining Table @ P " << physical_sdt_ptr;
|
||||||
#endif
|
#endif
|
||||||
if (!strncmp(sdt->sig, sig, 4)) {
|
if (!strncmp(sdt->sig, sig, 4)) {
|
||||||
#ifdef ACPI_DEBUG
|
#ifdef ACPI_DEBUG
|
||||||
dbg() << "ACPI: Found Table @ P " << physical_sdt_ptr;
|
dbg() << "ACPI: Found Table @ P " << physical_sdt_ptr;
|
||||||
#endif
|
#endif
|
||||||
return p_sdt;
|
return p_sdt;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
void StaticParser::init_facs()
|
void StaticParser::init_facs()
|
||||||
{
|
{
|
||||||
m_facs = find_table("FACS");
|
m_facs = find_table("FACS");
|
||||||
}
|
}
|
||||||
|
|
||||||
const FADTFlags::HardwareFeatures& StaticParser::hardware_features() const
|
const FADTFlags::HardwareFeatures& StaticParser::hardware_features() const
|
||||||
{
|
{
|
||||||
return m_hardware_flags;
|
return m_hardware_flags;
|
||||||
}
|
}
|
||||||
const FADTFlags::x86_Specific_Flags& StaticParser::x86_specific_flags() const
|
const FADTFlags::x86_Specific_Flags& StaticParser::x86_specific_flags() const
|
||||||
{
|
{
|
||||||
return m_x86_specific_flags;
|
return m_x86_specific_flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
void StaticParser::init_fadt()
|
void StaticParser::init_fadt()
|
||||||
{
|
{
|
||||||
klog() << "ACPI: Initializing Fixed ACPI data";
|
klog() << "ACPI: Initializing Fixed ACPI data";
|
||||||
klog() << "ACPI: Searching for the Fixed ACPI Data Table";
|
klog() << "ACPI: Searching for the Fixed ACPI Data Table";
|
||||||
|
|
||||||
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 checkup_region = MM.allocate_kernel_region(m_fadt.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser", Region::Access::Read);
|
||||||
auto* sdt = (const Structures::FADT*)checkup_region->vaddr().offset(m_fadt.offset_in_page()).as_ptr();
|
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*)fadt.as_ptr();
|
dbg() << "ACPI: FADT @ V " << sdt << ", P " << (void*)fadt.as_ptr();
|
||||||
#endif
|
#endif
|
||||||
klog() << "ACPI: Fixed ACPI data, Revision " << sdt->h.revision << ", Length " << sdt->h.length << " bytes";
|
klog() << "ACPI: Fixed ACPI data, Revision " << sdt->h.revision << ", Length " << sdt->h.length << " bytes";
|
||||||
klog() << "ACPI: DSDT " << PhysicalAddress(sdt->dsdt_ptr);
|
klog() << "ACPI: DSDT " << PhysicalAddress(sdt->dsdt_ptr);
|
||||||
m_x86_specific_flags.cmos_rtc_not_present = (sdt->ia_pc_boot_arch_flags & (u8)FADTFlags::IA_PC_Flags::CMOS_RTC_Not_Present);
|
m_x86_specific_flags.cmos_rtc_not_present = (sdt->ia_pc_boot_arch_flags & (u8)FADTFlags::IA_PC_Flags::CMOS_RTC_Not_Present);
|
||||||
m_x86_specific_flags.keyboard_8042 = (sdt->ia_pc_boot_arch_flags & (u8)FADTFlags::IA_PC_Flags::PS2_8042);
|
m_x86_specific_flags.keyboard_8042 = (sdt->ia_pc_boot_arch_flags & (u8)FADTFlags::IA_PC_Flags::PS2_8042);
|
||||||
m_x86_specific_flags.legacy_devices = (sdt->ia_pc_boot_arch_flags & (u8)FADTFlags::IA_PC_Flags::Legacy_Devices);
|
m_x86_specific_flags.legacy_devices = (sdt->ia_pc_boot_arch_flags & (u8)FADTFlags::IA_PC_Flags::Legacy_Devices);
|
||||||
m_x86_specific_flags.msi_not_supported = (sdt->ia_pc_boot_arch_flags & (u8)FADTFlags::IA_PC_Flags::MSI_Not_Supported);
|
m_x86_specific_flags.msi_not_supported = (sdt->ia_pc_boot_arch_flags & (u8)FADTFlags::IA_PC_Flags::MSI_Not_Supported);
|
||||||
m_x86_specific_flags.vga_not_present = (sdt->ia_pc_boot_arch_flags & (u8)FADTFlags::IA_PC_Flags::VGA_Not_Present);
|
m_x86_specific_flags.vga_not_present = (sdt->ia_pc_boot_arch_flags & (u8)FADTFlags::IA_PC_Flags::VGA_Not_Present);
|
||||||
|
|
||||||
m_hardware_flags.cpu_software_sleep = (sdt->flags & (u32)FADTFlags::FeatureFlags::CPU_SW_SLP);
|
m_hardware_flags.cpu_software_sleep = (sdt->flags & (u32)FADTFlags::FeatureFlags::CPU_SW_SLP);
|
||||||
m_hardware_flags.docking_capability = (sdt->flags & (u32)FADTFlags::FeatureFlags::DCK_CAP);
|
m_hardware_flags.docking_capability = (sdt->flags & (u32)FADTFlags::FeatureFlags::DCK_CAP);
|
||||||
m_hardware_flags.fix_rtc = (sdt->flags & (u32)FADTFlags::FeatureFlags::FIX_RTC);
|
m_hardware_flags.fix_rtc = (sdt->flags & (u32)FADTFlags::FeatureFlags::FIX_RTC);
|
||||||
m_hardware_flags.force_apic_cluster_model = (sdt->flags & (u32)FADTFlags::FeatureFlags::FORCE_APIC_CLUSTER_MODEL);
|
m_hardware_flags.force_apic_cluster_model = (sdt->flags & (u32)FADTFlags::FeatureFlags::FORCE_APIC_CLUSTER_MODEL);
|
||||||
m_hardware_flags.force_apic_physical_destination_mode = (sdt->flags & (u32)FADTFlags::FeatureFlags::FORCE_APIC_PHYSICAL_DESTINATION_MODE);
|
m_hardware_flags.force_apic_physical_destination_mode = (sdt->flags & (u32)FADTFlags::FeatureFlags::FORCE_APIC_PHYSICAL_DESTINATION_MODE);
|
||||||
m_hardware_flags.hardware_reduced_acpi = (sdt->flags & (u32)FADTFlags::FeatureFlags::HW_REDUCED_ACPI);
|
m_hardware_flags.hardware_reduced_acpi = (sdt->flags & (u32)FADTFlags::FeatureFlags::HW_REDUCED_ACPI);
|
||||||
m_hardware_flags.headless = (sdt->flags & (u32)FADTFlags::FeatureFlags::HEADLESS);
|
m_hardware_flags.headless = (sdt->flags & (u32)FADTFlags::FeatureFlags::HEADLESS);
|
||||||
m_hardware_flags.low_power_s0_idle_capable = (sdt->flags & (u32)FADTFlags::FeatureFlags::LOW_POWER_S0_IDLE_CAPABLE);
|
m_hardware_flags.low_power_s0_idle_capable = (sdt->flags & (u32)FADTFlags::FeatureFlags::LOW_POWER_S0_IDLE_CAPABLE);
|
||||||
m_hardware_flags.multiprocessor_c2 = (sdt->flags & (u32)FADTFlags::FeatureFlags::P_LVL2_UP);
|
m_hardware_flags.multiprocessor_c2 = (sdt->flags & (u32)FADTFlags::FeatureFlags::P_LVL2_UP);
|
||||||
m_hardware_flags.pci_express_wake = (sdt->flags & (u32)FADTFlags::FeatureFlags::PCI_EXP_WAK);
|
m_hardware_flags.pci_express_wake = (sdt->flags & (u32)FADTFlags::FeatureFlags::PCI_EXP_WAK);
|
||||||
m_hardware_flags.power_button = (sdt->flags & (u32)FADTFlags::FeatureFlags::PWR_BUTTON);
|
m_hardware_flags.power_button = (sdt->flags & (u32)FADTFlags::FeatureFlags::PWR_BUTTON);
|
||||||
m_hardware_flags.processor_c1 = (sdt->flags & (u32)FADTFlags::FeatureFlags::PROC_C1);
|
m_hardware_flags.processor_c1 = (sdt->flags & (u32)FADTFlags::FeatureFlags::PROC_C1);
|
||||||
m_hardware_flags.remote_power_on_capable = (sdt->flags & (u32)FADTFlags::FeatureFlags::REMOTE_POWER_ON_CAPABLE);
|
m_hardware_flags.remote_power_on_capable = (sdt->flags & (u32)FADTFlags::FeatureFlags::REMOTE_POWER_ON_CAPABLE);
|
||||||
m_hardware_flags.reset_register_supported = (sdt->flags & (u32)FADTFlags::FeatureFlags::RESET_REG_SUPPORTED);
|
m_hardware_flags.reset_register_supported = (sdt->flags & (u32)FADTFlags::FeatureFlags::RESET_REG_SUPPORTED);
|
||||||
m_hardware_flags.rtc_s4 = (sdt->flags & (u32)FADTFlags::FeatureFlags::RTC_s4);
|
m_hardware_flags.rtc_s4 = (sdt->flags & (u32)FADTFlags::FeatureFlags::RTC_s4);
|
||||||
m_hardware_flags.s4_rtc_status_valid = (sdt->flags & (u32)FADTFlags::FeatureFlags::S4_RTC_STS_VALID);
|
m_hardware_flags.s4_rtc_status_valid = (sdt->flags & (u32)FADTFlags::FeatureFlags::S4_RTC_STS_VALID);
|
||||||
m_hardware_flags.sealed_case = (sdt->flags & (u32)FADTFlags::FeatureFlags::SEALED_CASE);
|
m_hardware_flags.sealed_case = (sdt->flags & (u32)FADTFlags::FeatureFlags::SEALED_CASE);
|
||||||
m_hardware_flags.sleep_button = (sdt->flags & (u32)FADTFlags::FeatureFlags::SLP_BUTTON);
|
m_hardware_flags.sleep_button = (sdt->flags & (u32)FADTFlags::FeatureFlags::SLP_BUTTON);
|
||||||
m_hardware_flags.timer_value_extension = (sdt->flags & (u32)FADTFlags::FeatureFlags::TMR_VAL_EXT);
|
m_hardware_flags.timer_value_extension = (sdt->flags & (u32)FADTFlags::FeatureFlags::TMR_VAL_EXT);
|
||||||
m_hardware_flags.use_platform_clock = (sdt->flags & (u32)FADTFlags::FeatureFlags::USE_PLATFORM_CLOCK);
|
m_hardware_flags.use_platform_clock = (sdt->flags & (u32)FADTFlags::FeatureFlags::USE_PLATFORM_CLOCK);
|
||||||
m_hardware_flags.wbinvd = (sdt->flags & (u32)FADTFlags::FeatureFlags::WBINVD);
|
m_hardware_flags.wbinvd = (sdt->flags & (u32)FADTFlags::FeatureFlags::WBINVD);
|
||||||
m_hardware_flags.wbinvd_flush = (sdt->flags & (u32)FADTFlags::FeatureFlags::WBINVD_FLUSH);
|
m_hardware_flags.wbinvd_flush = (sdt->flags & (u32)FADTFlags::FeatureFlags::WBINVD_FLUSH);
|
||||||
}
|
}
|
||||||
|
|
||||||
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 region = MM.allocate_kernel_region(m_fadt.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser", Region::Access::Read);
|
||||||
auto* fadt = (const Structures::FADT*)region->vaddr().offset(m_fadt.offset_in_page()).as_ptr();
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 (structure.address_space) {
|
||||||
case (u8)GenericAddressStructure::AddressSpace::SystemIO: {
|
case (u8)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) {
|
||||||
case (u8)GenericAddressStructure::AccessSize::QWord: {
|
case (u8)GenericAddressStructure::AccessSize::QWord: {
|
||||||
dbg() << "Trying to send QWord to IO port";
|
dbg() << "Trying to send QWord to IO port";
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
case (u8)GenericAddressStructure::AccessSize::Undefined: {
|
|
||||||
dbg() << "ACPI Warning: Unknown access size " << structure.access_size;
|
|
||||||
ASSERT(structure.bit_width != (u8)GenericAddressStructure::BitWidth::QWord);
|
|
||||||
ASSERT(structure.bit_width != (u8)GenericAddressStructure::BitWidth::Undefined);
|
|
||||||
dbg() << "ACPI: Bit Width - " << structure.bit_width << " bits";
|
|
||||||
address.out(value, structure.bit_width);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
address.out(value, (8 << (structure.access_size - 1)));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
case (u8)GenericAddressStructure::AddressSpace::SystemMemory: {
|
case (u8)GenericAddressStructure::AccessSize::Undefined: {
|
||||||
auto p_reg = PhysicalAddress(structure.address);
|
dbg() << "ACPI Warning: Unknown access size " << structure.access_size;
|
||||||
auto p_region = MM.allocate_kernel_region(p_reg.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser", Region::Access::Read);
|
ASSERT(structure.bit_width != (u8)GenericAddressStructure::BitWidth::QWord);
|
||||||
dbg() << "ACPI: Sending value 0x" << String::format("%x", value) << " to " << p_reg;
|
ASSERT(structure.bit_width != (u8)GenericAddressStructure::BitWidth::Undefined);
|
||||||
switch (structure.access_size) {
|
dbg() << "ACPI: Bit Width - " << structure.bit_width << " bits";
|
||||||
case (u8)GenericAddressStructure::AccessSize::Byte: {
|
address.out(value, structure.bit_width);
|
||||||
auto* reg = (volatile u8*)p_region->vaddr().offset(p_reg.offset_in_page()).as_ptr();
|
break;
|
||||||
(*reg) = value;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case (u8)GenericAddressStructure::AccessSize::Word: {
|
|
||||||
auto* reg = (volatile u16*)p_region->vaddr().offset(p_reg.offset_in_page()).as_ptr();
|
|
||||||
(*reg) = value;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case (u8)GenericAddressStructure::AccessSize::DWord: {
|
|
||||||
auto* reg = (volatile u32*)p_region->vaddr().offset(p_reg.offset_in_page()).as_ptr();
|
|
||||||
(*reg) = value;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case (u8)GenericAddressStructure::AccessSize::QWord: {
|
|
||||||
auto* reg = (volatile u64*)p_region->vaddr().offset(p_reg.offset_in_page()).as_ptr();
|
|
||||||
(*reg) = value;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
case (u8)GenericAddressStructure::AddressSpace::PCIConfigurationSpace: {
|
default:
|
||||||
// According to the ACPI specification 6.2, page 168, PCI addresses must be confined to devices on Segment group 0, bus 0.
|
address.out(value, (8 << (structure.access_size - 1)));
|
||||||
auto pci_address = PCI::Address(0, 0, ((structure.address >> 24) & 0xFF), ((structure.address >> 16) & 0xFF));
|
break;
|
||||||
dbg() << "ACPI: Sending value 0x" << String::format("%x", value) << " to " << pci_address;
|
}
|
||||||
u32 offset_in_pci_address = structure.address & 0xFFFF;
|
return;
|
||||||
if (structure.access_size == (u8)GenericAddressStructure::AccessSize::QWord) {
|
}
|
||||||
dbg() << "Trying to send QWord to PCI configuration space";
|
case (u8)GenericAddressStructure::AddressSpace::SystemMemory: {
|
||||||
ASSERT_NOT_REACHED();
|
auto p_reg = PhysicalAddress(structure.address);
|
||||||
}
|
auto p_region = MM.allocate_kernel_region(p_reg.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser", Region::Access::Read);
|
||||||
ASSERT(structure.access_size != (u8)GenericAddressStructure::AccessSize::Undefined);
|
dbg() << "ACPI: Sending value 0x" << String::format("%x", value) << " to " << p_reg;
|
||||||
PCI::raw_access(pci_address, offset_in_pci_address, (1 << (structure.access_size - 1)), value);
|
switch (structure.access_size) {
|
||||||
return;
|
case (u8)GenericAddressStructure::AccessSize::Byte: {
|
||||||
|
auto* reg = (volatile u8*)p_region->vaddr().offset(p_reg.offset_in_page()).as_ptr();
|
||||||
|
(*reg) = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (u8)GenericAddressStructure::AccessSize::Word: {
|
||||||
|
auto* reg = (volatile u16*)p_region->vaddr().offset(p_reg.offset_in_page()).as_ptr();
|
||||||
|
(*reg) = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (u8)GenericAddressStructure::AccessSize::DWord: {
|
||||||
|
auto* reg = (volatile u32*)p_region->vaddr().offset(p_reg.offset_in_page()).as_ptr();
|
||||||
|
(*reg) = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case (u8)GenericAddressStructure::AccessSize::QWord: {
|
||||||
|
auto* reg = (volatile u64*)p_region->vaddr().offset(p_reg.offset_in_page()).as_ptr();
|
||||||
|
(*reg) = value;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case (u8)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.
|
||||||
|
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;
|
||||||
|
u32 offset_in_pci_address = structure.address & 0xFFFF;
|
||||||
|
if (structure.access_size == (u8)GenericAddressStructure::AccessSize::QWord) {
|
||||||
|
dbg() << "Trying to send QWord to PCI configuration space";
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
ASSERT(structure.access_size != (u8)GenericAddressStructure::AccessSize::Undefined);
|
||||||
|
PCI::raw_access(pci_address, offset_in_pci_address, (1 << (structure.access_size - 1)), value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
default:
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
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 region = MM.allocate_kernel_region(m_fadt.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser", Region::Access::Read);
|
||||||
auto* fadt = (const Structures::FADT*)region->vaddr().offset(m_fadt.offset_in_page()).as_ptr();
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
void StaticParser::try_acpi_reboot()
|
||||||
|
{
|
||||||
|
InterruptDisabler disabler;
|
||||||
|
if (!can_reboot()) {
|
||||||
|
klog() << "ACPI: Reboot, Not supported!";
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
#ifdef ACPI_DEBUG
|
||||||
|
dbg() << "ACPI: Rebooting, Probing FADT (" << m_fadt << ")";
|
||||||
|
#endif
|
||||||
|
|
||||||
void StaticParser::try_acpi_reboot()
|
auto region = MM.allocate_kernel_region(m_fadt.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser", Region::Access::Read);
|
||||||
{
|
auto* fadt = (const Structures::FADT*)region->vaddr().offset(m_fadt.offset_in_page()).as_ptr();
|
||||||
InterruptDisabler disabler;
|
ASSERT(validate_reset_register());
|
||||||
if (!can_reboot()) {
|
access_generic_address(fadt->reset_reg, fadt->reset_value);
|
||||||
klog() << "ACPI: Reboot, Not supported!";
|
for (;;)
|
||||||
return;
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StaticParser::try_acpi_shutdown()
|
||||||
|
{
|
||||||
|
klog() << "ACPI: Shutdown is not supported with the current configuration, Abort!";
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t StaticParser::get_table_size(PhysicalAddress table_header)
|
||||||
|
{
|
||||||
|
InterruptDisabler disabler;
|
||||||
|
#ifdef ACPI_DEBUG
|
||||||
|
dbg() << "ACPI: Checking SDT Length";
|
||||||
|
#endif
|
||||||
|
auto region = MM.allocate_kernel_region(table_header.page_base(), (PAGE_SIZE * 2), "ACPI get_table_size()", Region::Access::Read);
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
InterruptDisabler disabler;
|
||||||
|
#ifdef ACPI_DEBUG
|
||||||
|
dbg() << "ACPI: Checking SDT Revision";
|
||||||
|
#endif
|
||||||
|
auto region = MM.allocate_kernel_region(table_header.page_base(), (PAGE_SIZE * 2), "ACPI get_table_revision()", Region::Access::Read);
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
#ifdef ACPI_DEBUG
|
||||||
|
dbg() << "ACPI: Checking Main SDT Length to choose the correct mapping size";
|
||||||
|
#endif
|
||||||
|
ASSERT(!m_main_system_description_table.is_null());
|
||||||
|
auto length = get_table_size(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 = (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);
|
||||||
|
|
||||||
|
if (m_xsdt_supported) {
|
||||||
|
volatile auto* xsdt = (volatile Structures::XSDT*)sdt;
|
||||||
|
klog() << "ACPI: Using XSDT, Enumerating tables @ " << m_main_system_description_table;
|
||||||
|
klog() << "ACPI: XSDT Revision " << revision << ", Total length - " << length;
|
||||||
|
#ifdef ACPI_DEBUG
|
||||||
|
dbg() << "ACPI: XSDT pointer @ V " << xsdt;
|
||||||
|
#endif
|
||||||
|
for (u32 i = 0; i < ((length - sizeof(Structures::SDTHeader)) / sizeof(u64)); i++) {
|
||||||
|
#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]);
|
||||||
|
#endif
|
||||||
|
m_sdt_pointers.append(PhysicalAddress(xsdt->table_ptrs[i]));
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
volatile auto* rsdt = (volatile Structures::RSDT*)sdt;
|
||||||
|
klog() << "ACPI: Using RSDT, Enumerating tables @ " << m_main_system_description_table;
|
||||||
|
klog() << "ACPI: RSDT Revision " << revision << ", Total length - " << length;
|
||||||
#ifdef ACPI_DEBUG
|
#ifdef ACPI_DEBUG
|
||||||
dbg() << "ACPI: Rebooting, Probing FADT (" << m_fadt << ")";
|
dbg() << "ACPI: RSDT pointer @ V " << rsdt;
|
||||||
#endif
|
#endif
|
||||||
|
for (u32 i = 0; i < ((length - sizeof(Structures::SDTHeader)) / sizeof(u32)); i++) {
|
||||||
auto region = MM.allocate_kernel_region(m_fadt.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser", Region::Access::Read);
|
#ifdef ACPI_DEBUG
|
||||||
auto* fadt = (const Structures::FADT*)region->vaddr().offset(m_fadt.offset_in_page()).as_ptr();
|
dbg() << "ACPI: Found new table [" << i << "], @ V 0x" << String::format("%x", &rsdt->table_ptrs[i]) << " - P 0x" << String::format("%x", rsdt->table_ptrs[i]);
|
||||||
ASSERT(validate_reset_register());
|
#endif
|
||||||
access_generic_address(fadt->reset_reg, fadt->reset_value);
|
m_sdt_pointers.append(PhysicalAddress(rsdt->table_ptrs[i]));
|
||||||
for (;;)
|
}
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void StaticParser::try_acpi_shutdown()
|
void StaticParser::locate_main_system_description_table()
|
||||||
{
|
{
|
||||||
klog() << "ACPI: Shutdown is not supported with the current configuration, Abort!";
|
auto rsdp_region = MM.allocate_kernel_region(m_rsdp.page_base(), (PAGE_SIZE * 2), "ACPI Static Parser Initialization", Region::Access::Read, false, true);
|
||||||
}
|
volatile auto* rsdp = (Structures::RSDPDescriptor20*)rsdp_region->vaddr().offset(m_rsdp.offset_in_page()).as_ptr();
|
||||||
|
if (rsdp->base.revision == 0) {
|
||||||
size_t StaticParser::get_table_size(PhysicalAddress table_header)
|
m_xsdt_supported = false;
|
||||||
{
|
} else if (rsdp->base.revision >= 2) {
|
||||||
InterruptDisabler disabler;
|
if (rsdp->xsdt_ptr != (u64) nullptr) {
|
||||||
#ifdef ACPI_DEBUG
|
m_xsdt_supported = true;
|
||||||
dbg() << "ACPI: Checking SDT Length";
|
|
||||||
#endif
|
|
||||||
auto region = MM.allocate_kernel_region(table_header.page_base(), (PAGE_SIZE * 2), "ACPI get_table_size()", Region::Access::Read);
|
|
||||||
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)
|
|
||||||
{
|
|
||||||
InterruptDisabler disabler;
|
|
||||||
#ifdef ACPI_DEBUG
|
|
||||||
dbg() << "ACPI: Checking SDT Revision";
|
|
||||||
#endif
|
|
||||||
auto region = MM.allocate_kernel_region(table_header.page_base(), (PAGE_SIZE * 2), "ACPI get_table_revision()", Region::Access::Read);
|
|
||||||
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()
|
|
||||||
{
|
|
||||||
#ifdef ACPI_DEBUG
|
|
||||||
dbg() << "ACPI: Checking Main SDT Length to choose the correct mapping size";
|
|
||||||
#endif
|
|
||||||
ASSERT(!m_main_system_description_table.is_null());
|
|
||||||
auto length = get_table_size(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 = (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);
|
|
||||||
|
|
||||||
if (m_xsdt_supported) {
|
|
||||||
volatile auto* xsdt = (volatile Structures::XSDT*)sdt;
|
|
||||||
klog() << "ACPI: Using XSDT, Enumerating tables @ " << m_main_system_description_table;
|
|
||||||
klog() << "ACPI: XSDT Revision " << revision << ", Total length - " << length;
|
|
||||||
#ifdef ACPI_DEBUG
|
|
||||||
dbg() << "ACPI: XSDT pointer @ V " << xsdt;
|
|
||||||
#endif
|
|
||||||
for (u32 i = 0; i < ((length - sizeof(Structures::SDTHeader)) / sizeof(u64)); i++) {
|
|
||||||
#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]);
|
|
||||||
#endif
|
|
||||||
m_sdt_pointers.append(PhysicalAddress(xsdt->table_ptrs[i]));
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
volatile auto* rsdt = (volatile Structures::RSDT*)sdt;
|
|
||||||
klog() << "ACPI: Using RSDT, Enumerating tables @ " << m_main_system_description_table;
|
|
||||||
klog() << "ACPI: RSDT Revision " << revision << ", Total length - " << length;
|
|
||||||
#ifdef ACPI_DEBUG
|
|
||||||
dbg() << "ACPI: RSDT pointer @ V " << rsdt;
|
|
||||||
#endif
|
|
||||||
for (u32 i = 0; i < ((length - sizeof(Structures::SDTHeader)) / sizeof(u32)); i++) {
|
|
||||||
#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]);
|
|
||||||
#endif
|
|
||||||
m_sdt_pointers.append(PhysicalAddress(rsdt->table_ptrs[i]));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
volatile auto* rsdp = (Structures::RSDPDescriptor20*)rsdp_region->vaddr().offset(m_rsdp.offset_in_page()).as_ptr();
|
|
||||||
if (rsdp->base.revision == 0) {
|
|
||||||
m_xsdt_supported = false;
|
m_xsdt_supported = false;
|
||||||
} else if (rsdp->base.revision >= 2) {
|
|
||||||
if (rsdp->xsdt_ptr != (u64) nullptr) {
|
|
||||||
m_xsdt_supported = true;
|
|
||||||
} else {
|
|
||||||
m_xsdt_supported = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!m_xsdt_supported) {
|
|
||||||
m_main_system_description_table = PhysicalAddress(rsdp->base.rsdt_ptr);
|
|
||||||
} else {
|
|
||||||
m_main_system_description_table = PhysicalAddress(rsdp->xsdt_ptr);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!m_xsdt_supported) {
|
||||||
StaticParser::StaticParser()
|
m_main_system_description_table = PhysicalAddress(rsdp->base.rsdt_ptr);
|
||||||
: Parser(true)
|
} else {
|
||||||
, m_rsdp(StaticParsing::search_rsdp())
|
m_main_system_description_table = PhysicalAddress(rsdp->xsdt_ptr);
|
||||||
{
|
|
||||||
if (!m_rsdp.is_null()) {
|
|
||||||
klog() << "ACPI: Using RSDP @ " << m_rsdp;
|
|
||||||
m_operable = true;
|
|
||||||
locate_static_data();
|
|
||||||
} else {
|
|
||||||
m_operable = false;
|
|
||||||
klog() << "ACPI: Disabled, due to RSDP being absent";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
StaticParser::StaticParser(PhysicalAddress rsdp)
|
StaticParser::StaticParser()
|
||||||
: Parser(true)
|
: Parser(true)
|
||||||
, m_rsdp(rsdp)
|
, m_rsdp(StaticParsing::search_rsdp())
|
||||||
{
|
{
|
||||||
klog() << "ACPI: Using RSDP @ " << rsdp;
|
if (!m_rsdp.is_null()) {
|
||||||
|
klog() << "ACPI: Using RSDP @ " << m_rsdp;
|
||||||
m_operable = true;
|
m_operable = true;
|
||||||
locate_static_data();
|
locate_static_data();
|
||||||
}
|
} else {
|
||||||
|
m_operable = false;
|
||||||
PhysicalAddress StaticParsing::search_rsdp_in_ebda(u16 ebda_segment)
|
klog() << "ACPI: Disabled, due to RSDP being absent";
|
||||||
{
|
|
||||||
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
|
|
||||||
dbg() << "ACPI: Looking for RSDP in EBDA @ V " << (void*)rsdp_str << ", P " << (void*)p_rsdp_str;
|
|
||||||
#endif
|
|
||||||
if (!strncmp("RSD PTR ", rsdp_str, strlen("RSD PTR ")))
|
|
||||||
return PhysicalAddress((FlatPtr)p_rsdp_str);
|
|
||||||
p_rsdp_str += 16;
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
PhysicalAddress StaticParsing::search_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);
|
|
||||||
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
|
|
||||||
dbg() << "ACPI: Looking for RSDP in BIOS ROM area @ V " << (void*)rsdp_str << ", P " << (void*)p_rsdp_str;
|
|
||||||
#endif
|
|
||||||
if (!strncmp("RSD PTR ", rsdp_str, strlen("RSD PTR ")))
|
|
||||||
return PhysicalAddress((FlatPtr)p_rsdp_str);
|
|
||||||
p_rsdp_str += 16;
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool StaticParsing::validate_table(Structures::SDTHeader& v_header, size_t length)
|
|
||||||
{
|
|
||||||
u8 checksum = 0;
|
|
||||||
auto* sdt = (u8*)&v_header;
|
|
||||||
for (size_t i = 0; i < length; i++)
|
|
||||||
checksum += sdt[i];
|
|
||||||
if (checksum == 0)
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
PhysicalAddress StaticParsing::search_rsdp()
|
|
||||||
{
|
|
||||||
PhysicalAddress rsdp;
|
|
||||||
auto region = MM.allocate_kernel_region(PhysicalAddress(0), PAGE_SIZE, "ACPI RSDP Searching", Region::Access::Read);
|
|
||||||
u16 ebda_seg = (u16) * ((uint16_t*)((region->vaddr().get() & PAGE_MASK) + 0x40e));
|
|
||||||
klog() << "ACPI: Probing EBDA, Segment 0x" << String::format("%x", ebda_seg);
|
|
||||||
|
|
||||||
rsdp = search_rsdp_in_ebda(ebda_seg);
|
|
||||||
if (!rsdp.is_null())
|
|
||||||
return rsdp;
|
|
||||||
return search_rsdp_in_bios_area();
|
|
||||||
}
|
|
||||||
|
|
||||||
PhysicalAddress StaticParsing::search_table(PhysicalAddress rsdp, const char* signature)
|
|
||||||
{
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
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();
|
|
||||||
if (rsdp_ptr->base.revision == 0) {
|
|
||||||
return search_table_in_rsdt(PhysicalAddress(rsdp_ptr->base.rsdt_ptr), signature);
|
|
||||||
}
|
|
||||||
if (rsdp_ptr->base.revision >= 2) {
|
|
||||||
if (rsdp_ptr->xsdt_ptr != (u64) nullptr)
|
|
||||||
return search_table_in_xsdt(PhysicalAddress(rsdp_ptr->xsdt_ptr), signature);
|
|
||||||
return search_table_in_rsdt(PhysicalAddress(rsdp_ptr->base.rsdt_ptr), signature);
|
|
||||||
}
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
}
|
|
||||||
|
|
||||||
PhysicalAddress StaticParsing::search_table_in_xsdt(PhysicalAddress xsdt, const char* signature)
|
|
||||||
{
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
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();
|
|
||||||
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))
|
|
||||||
return PhysicalAddress((FlatPtr)xsdt_ptr->table_ptrs[i]);
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
bool StaticParsing::match_table_signature(PhysicalAddress table_header, const char* signature)
|
|
||||||
{
|
|
||||||
// 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.
|
|
||||||
|
|
||||||
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();
|
|
||||||
return !strncmp(const_cast<const char*>(table_ptr->h.sig), signature, 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
PhysicalAddress StaticParsing::search_table_in_rsdt(PhysicalAddress rsdt, const char* signature)
|
|
||||||
{
|
|
||||||
// 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.
|
|
||||||
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_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++) {
|
|
||||||
if (match_table_signature(PhysicalAddress((FlatPtr)rsdt_ptr->table_ptrs[i]), signature))
|
|
||||||
return PhysicalAddress((FlatPtr)rsdt_ptr->table_ptrs[i]);
|
|
||||||
}
|
|
||||||
return {};
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StaticParser::StaticParser(PhysicalAddress rsdp)
|
||||||
|
: Parser(true)
|
||||||
|
, m_rsdp(rsdp)
|
||||||
|
{
|
||||||
|
klog() << "ACPI: Using RSDP @ " << rsdp;
|
||||||
|
m_operable = true;
|
||||||
|
locate_static_data();
|
||||||
|
}
|
||||||
|
|
||||||
|
PhysicalAddress StaticParsing::search_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);
|
||||||
|
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
|
||||||
|
dbg() << "ACPI: Looking for RSDP in EBDA @ V " << (void*)rsdp_str << ", P " << (void*)p_rsdp_str;
|
||||||
|
#endif
|
||||||
|
if (!strncmp("RSD PTR ", rsdp_str, strlen("RSD PTR ")))
|
||||||
|
return PhysicalAddress((FlatPtr)p_rsdp_str);
|
||||||
|
p_rsdp_str += 16;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
PhysicalAddress StaticParsing::search_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);
|
||||||
|
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
|
||||||
|
dbg() << "ACPI: Looking for RSDP in BIOS ROM area @ V " << (void*)rsdp_str << ", P " << (void*)p_rsdp_str;
|
||||||
|
#endif
|
||||||
|
if (!strncmp("RSD PTR ", rsdp_str, strlen("RSD PTR ")))
|
||||||
|
return PhysicalAddress((FlatPtr)p_rsdp_str);
|
||||||
|
p_rsdp_str += 16;
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool StaticParsing::validate_table(Structures::SDTHeader& v_header, size_t length)
|
||||||
|
{
|
||||||
|
u8 checksum = 0;
|
||||||
|
auto* sdt = (u8*)&v_header;
|
||||||
|
for (size_t i = 0; i < length; i++)
|
||||||
|
checksum += sdt[i];
|
||||||
|
if (checksum == 0)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
PhysicalAddress StaticParsing::search_rsdp()
|
||||||
|
{
|
||||||
|
PhysicalAddress rsdp;
|
||||||
|
auto region = MM.allocate_kernel_region(PhysicalAddress(0), PAGE_SIZE, "ACPI RSDP Searching", Region::Access::Read);
|
||||||
|
u16 ebda_seg = (u16) * ((uint16_t*)((region->vaddr().get() & PAGE_MASK) + 0x40e));
|
||||||
|
klog() << "ACPI: Probing EBDA, Segment 0x" << String::format("%x", ebda_seg);
|
||||||
|
|
||||||
|
rsdp = search_rsdp_in_ebda(ebda_seg);
|
||||||
|
if (!rsdp.is_null())
|
||||||
|
return rsdp;
|
||||||
|
return search_rsdp_in_bios_area();
|
||||||
|
}
|
||||||
|
|
||||||
|
PhysicalAddress StaticParsing::search_table(PhysicalAddress rsdp, const char* signature)
|
||||||
|
{
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
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();
|
||||||
|
if (rsdp_ptr->base.revision == 0) {
|
||||||
|
return search_table_in_rsdt(PhysicalAddress(rsdp_ptr->base.rsdt_ptr), signature);
|
||||||
|
}
|
||||||
|
if (rsdp_ptr->base.revision >= 2) {
|
||||||
|
if (rsdp_ptr->xsdt_ptr != (u64) nullptr)
|
||||||
|
return search_table_in_xsdt(PhysicalAddress(rsdp_ptr->xsdt_ptr), signature);
|
||||||
|
return search_table_in_rsdt(PhysicalAddress(rsdp_ptr->base.rsdt_ptr), signature);
|
||||||
|
}
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
|
PhysicalAddress StaticParsing::search_table_in_xsdt(PhysicalAddress xsdt, const char* signature)
|
||||||
|
{
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
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();
|
||||||
|
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))
|
||||||
|
return PhysicalAddress((FlatPtr)xsdt_ptr->table_ptrs[i]);
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StaticParsing::match_table_signature(PhysicalAddress table_header, const char* signature)
|
||||||
|
{
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
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();
|
||||||
|
return !strncmp(const_cast<const char*>(table_ptr->h.sig), signature, 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
PhysicalAddress StaticParsing::search_table_in_rsdt(PhysicalAddress rsdt, const char* signature)
|
||||||
|
{
|
||||||
|
// 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.
|
||||||
|
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_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++) {
|
||||||
|
if (match_table_signature(PhysicalAddress((FlatPtr)rsdt_ptr->table_ptrs[i]), signature))
|
||||||
|
return PhysicalAddress((FlatPtr)rsdt_ptr->table_ptrs[i]);
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,48 +32,48 @@
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
namespace ACPI {
|
namespace ACPI {
|
||||||
|
|
||||||
class StaticParser : Parser {
|
class StaticParser : Parser {
|
||||||
public:
|
public:
|
||||||
static void initialize(PhysicalAddress rsdp);
|
static void initialize(PhysicalAddress rsdp);
|
||||||
static void initialize_without_rsdp();
|
static void initialize_without_rsdp();
|
||||||
static bool is_initialized();
|
static bool is_initialized();
|
||||||
|
|
||||||
virtual PhysicalAddress find_table(const char* sig) override;
|
virtual PhysicalAddress find_table(const char* sig) override;
|
||||||
virtual void try_acpi_reboot() override;
|
virtual void try_acpi_reboot() override;
|
||||||
virtual bool can_reboot() override;
|
virtual bool can_reboot() override;
|
||||||
virtual bool can_shutdown() override { return false; }
|
virtual bool can_shutdown() override { return false; }
|
||||||
virtual void try_acpi_shutdown() override;
|
virtual void try_acpi_shutdown() override;
|
||||||
virtual bool is_operable() override { return m_operable; }
|
virtual bool is_operable() override { return m_operable; }
|
||||||
|
|
||||||
virtual const FADTFlags::HardwareFeatures& hardware_features() const override;
|
virtual const FADTFlags::HardwareFeatures& hardware_features() const override;
|
||||||
virtual const FADTFlags::x86_Specific_Flags& x86_specific_flags() const override;
|
virtual const FADTFlags::x86_Specific_Flags& x86_specific_flags() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
StaticParser();
|
StaticParser();
|
||||||
explicit StaticParser(PhysicalAddress);
|
explicit StaticParser(PhysicalAddress);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void locate_static_data();
|
void locate_static_data();
|
||||||
void locate_main_system_description_table();
|
void locate_main_system_description_table();
|
||||||
void initialize_main_system_description_table();
|
void initialize_main_system_description_table();
|
||||||
size_t get_table_size(PhysicalAddress);
|
size_t get_table_size(PhysicalAddress);
|
||||||
u8 get_table_revision(PhysicalAddress);
|
u8 get_table_revision(PhysicalAddress);
|
||||||
void init_fadt();
|
void init_fadt();
|
||||||
void init_facs();
|
void init_facs();
|
||||||
|
|
||||||
bool validate_reset_register();
|
bool validate_reset_register();
|
||||||
void access_generic_address(const Structures::GenericAddressStructure&, u32 value);
|
void access_generic_address(const Structures::GenericAddressStructure&, u32 value);
|
||||||
|
|
||||||
PhysicalAddress m_rsdp;
|
PhysicalAddress m_rsdp;
|
||||||
PhysicalAddress m_main_system_description_table;
|
PhysicalAddress m_main_system_description_table;
|
||||||
|
|
||||||
Vector<PhysicalAddress> m_sdt_pointers;
|
Vector<PhysicalAddress> m_sdt_pointers;
|
||||||
PhysicalAddress m_fadt;
|
PhysicalAddress m_fadt;
|
||||||
PhysicalAddress m_facs;
|
PhysicalAddress m_facs;
|
||||||
|
|
||||||
bool m_xsdt_supported;
|
bool m_xsdt_supported;
|
||||||
FADTFlags::HardwareFeatures m_hardware_flags;
|
FADTFlags::HardwareFeatures m_hardware_flags;
|
||||||
FADTFlags::x86_Specific_Flags m_x86_specific_flags;
|
FADTFlags::x86_Specific_Flags m_x86_specific_flags;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -35,315 +35,315 @@ namespace Kernel {
|
||||||
|
|
||||||
namespace ACPI {
|
namespace ACPI {
|
||||||
|
|
||||||
namespace FADTFlags {
|
namespace FADTFlags {
|
||||||
enum class FeatureFlags : u32 {
|
enum class FeatureFlags : u32 {
|
||||||
WBINVD = 1 << 0,
|
WBINVD = 1 << 0,
|
||||||
WBINVD_FLUSH = 1 << 1,
|
WBINVD_FLUSH = 1 << 1,
|
||||||
PROC_C1 = 1 << 2,
|
PROC_C1 = 1 << 2,
|
||||||
P_LVL2_UP = 1 << 3,
|
P_LVL2_UP = 1 << 3,
|
||||||
PWR_BUTTON = 1 << 4,
|
PWR_BUTTON = 1 << 4,
|
||||||
SLP_BUTTON = 1 << 5,
|
SLP_BUTTON = 1 << 5,
|
||||||
FIX_RTC = 1 << 6,
|
FIX_RTC = 1 << 6,
|
||||||
RTC_s4 = 1 << 7,
|
RTC_s4 = 1 << 7,
|
||||||
TMR_VAL_EXT = 1 << 8,
|
TMR_VAL_EXT = 1 << 8,
|
||||||
DCK_CAP = 1 << 9,
|
DCK_CAP = 1 << 9,
|
||||||
RESET_REG_SUPPORTED = 1 << 10,
|
RESET_REG_SUPPORTED = 1 << 10,
|
||||||
SEALED_CASE = 1 << 11,
|
SEALED_CASE = 1 << 11,
|
||||||
HEADLESS = 1 << 12,
|
HEADLESS = 1 << 12,
|
||||||
CPU_SW_SLP = 1 << 13,
|
CPU_SW_SLP = 1 << 13,
|
||||||
PCI_EXP_WAK = 1 << 14,
|
PCI_EXP_WAK = 1 << 14,
|
||||||
USE_PLATFORM_CLOCK = 1 << 15,
|
USE_PLATFORM_CLOCK = 1 << 15,
|
||||||
S4_RTC_STS_VALID = 1 << 16,
|
S4_RTC_STS_VALID = 1 << 16,
|
||||||
REMOTE_POWER_ON_CAPABLE = 1 << 17,
|
REMOTE_POWER_ON_CAPABLE = 1 << 17,
|
||||||
FORCE_APIC_CLUSTER_MODEL = 1 << 18,
|
FORCE_APIC_CLUSTER_MODEL = 1 << 18,
|
||||||
FORCE_APIC_PHYSICAL_DESTINATION_MODE = 1 << 19,
|
FORCE_APIC_PHYSICAL_DESTINATION_MODE = 1 << 19,
|
||||||
HW_REDUCED_ACPI = 1 << 20,
|
HW_REDUCED_ACPI = 1 << 20,
|
||||||
LOW_POWER_S0_IDLE_CAPABLE = 1 << 21
|
LOW_POWER_S0_IDLE_CAPABLE = 1 << 21
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class IA_PC_Flags : u8 {
|
enum class IA_PC_Flags : u8 {
|
||||||
Legacy_Devices = 1 << 0,
|
Legacy_Devices = 1 << 0,
|
||||||
PS2_8042 = 1 << 1,
|
PS2_8042 = 1 << 1,
|
||||||
VGA_Not_Present = 1 << 2,
|
VGA_Not_Present = 1 << 2,
|
||||||
MSI_Not_Supported = 1 << 3,
|
MSI_Not_Supported = 1 << 3,
|
||||||
PCIe_ASPM_Controls = 1 << 4,
|
PCIe_ASPM_Controls = 1 << 4,
|
||||||
CMOS_RTC_Not_Present = 1 << 5
|
CMOS_RTC_Not_Present = 1 << 5
|
||||||
};
|
};
|
||||||
|
|
||||||
struct [[gnu::packed]] HardwareFeatures
|
struct [[gnu::packed]] HardwareFeatures
|
||||||
{
|
{
|
||||||
bool wbinvd : 1;
|
bool wbinvd : 1;
|
||||||
bool wbinvd_flush : 1;
|
bool wbinvd_flush : 1;
|
||||||
bool processor_c1 : 1;
|
bool processor_c1 : 1;
|
||||||
bool multiprocessor_c2 : 1;
|
bool multiprocessor_c2 : 1;
|
||||||
bool power_button : 1;
|
bool power_button : 1;
|
||||||
bool sleep_button : 1;
|
bool sleep_button : 1;
|
||||||
bool fix_rtc : 1;
|
bool fix_rtc : 1;
|
||||||
bool rtc_s4 : 1;
|
bool rtc_s4 : 1;
|
||||||
bool timer_value_extension : 1;
|
bool timer_value_extension : 1;
|
||||||
bool docking_capability : 1;
|
bool docking_capability : 1;
|
||||||
bool reset_register_supported : 1;
|
bool reset_register_supported : 1;
|
||||||
bool sealed_case : 1;
|
bool sealed_case : 1;
|
||||||
bool headless : 1;
|
bool headless : 1;
|
||||||
bool cpu_software_sleep : 1;
|
bool cpu_software_sleep : 1;
|
||||||
bool pci_express_wake : 1;
|
bool pci_express_wake : 1;
|
||||||
bool use_platform_clock : 1;
|
bool use_platform_clock : 1;
|
||||||
bool s4_rtc_status_valid : 1;
|
bool s4_rtc_status_valid : 1;
|
||||||
bool remote_power_on_capable : 1;
|
bool remote_power_on_capable : 1;
|
||||||
bool force_apic_cluster_model : 1;
|
bool force_apic_cluster_model : 1;
|
||||||
bool force_apic_physical_destination_mode : 1;
|
bool force_apic_physical_destination_mode : 1;
|
||||||
bool hardware_reduced_acpi : 1;
|
bool hardware_reduced_acpi : 1;
|
||||||
bool low_power_s0_idle_capable : 1;
|
bool low_power_s0_idle_capable : 1;
|
||||||
};
|
};
|
||||||
struct [[gnu::packed]] x86_Specific_Flags
|
struct [[gnu::packed]] x86_Specific_Flags
|
||||||
{
|
{
|
||||||
bool legacy_devices : 1;
|
bool legacy_devices : 1;
|
||||||
bool keyboard_8042 : 1;
|
bool keyboard_8042 : 1;
|
||||||
bool vga_not_present : 1;
|
bool vga_not_present : 1;
|
||||||
bool msi_not_supported : 1;
|
bool msi_not_supported : 1;
|
||||||
bool cmos_rtc_not_present : 1;
|
bool cmos_rtc_not_present : 1;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace GenericAddressStructure {
|
namespace GenericAddressStructure {
|
||||||
enum class AddressSpace {
|
enum class AddressSpace {
|
||||||
SystemMemory = 0,
|
SystemMemory = 0,
|
||||||
SystemIO = 1,
|
SystemIO = 1,
|
||||||
PCIConfigurationSpace = 2,
|
PCIConfigurationSpace = 2,
|
||||||
EmbeddedController = 3,
|
EmbeddedController = 3,
|
||||||
SMBus = 4,
|
SMBus = 4,
|
||||||
PCC = 0xA,
|
PCC = 0xA,
|
||||||
FunctionalFixedHardware = 0x7F
|
FunctionalFixedHardware = 0x7F
|
||||||
};
|
};
|
||||||
enum class AccessSize {
|
enum class AccessSize {
|
||||||
Undefined = 0,
|
Undefined = 0,
|
||||||
Byte = 1,
|
Byte = 1,
|
||||||
Word = 2,
|
Word = 2,
|
||||||
DWord = 3,
|
DWord = 3,
|
||||||
QWord = 4
|
QWord = 4
|
||||||
};
|
};
|
||||||
enum class BitWidth {
|
enum class BitWidth {
|
||||||
Undefined = 0,
|
Undefined = 0,
|
||||||
Byte = 8,
|
Byte = 8,
|
||||||
Word = 16,
|
Word = 16,
|
||||||
DWord = 32,
|
DWord = 32,
|
||||||
QWord = 64
|
QWord = 64
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace Structures {
|
namespace Structures {
|
||||||
struct [[gnu::packed]] RSDPDescriptor
|
struct [[gnu::packed]] RSDPDescriptor
|
||||||
{
|
{
|
||||||
char sig[8];
|
char sig[8];
|
||||||
u8 checksum;
|
u8 checksum;
|
||||||
char oem_id[6];
|
char oem_id[6];
|
||||||
u8 revision;
|
u8 revision;
|
||||||
u32 rsdt_ptr;
|
u32 rsdt_ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct [[gnu::packed]] RSDPDescriptor20
|
struct [[gnu::packed]] RSDPDescriptor20
|
||||||
{
|
{
|
||||||
RSDPDescriptor base;
|
RSDPDescriptor base;
|
||||||
u32 length;
|
u32 length;
|
||||||
u64 xsdt_ptr;
|
u64 xsdt_ptr;
|
||||||
u8 ext_checksum;
|
u8 ext_checksum;
|
||||||
u8 reserved[3];
|
u8 reserved[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct [[gnu::packed]] SDTHeader
|
struct [[gnu::packed]] SDTHeader
|
||||||
{
|
{
|
||||||
char sig[4];
|
char sig[4];
|
||||||
u32 length;
|
u32 length;
|
||||||
u8 revision;
|
u8 revision;
|
||||||
u8 checksum;
|
u8 checksum;
|
||||||
char oem_id[6];
|
char oem_id[6];
|
||||||
char oem_table_id[8];
|
char oem_table_id[8];
|
||||||
u32 oem_revision;
|
u32 oem_revision;
|
||||||
u32 creator_id;
|
u32 creator_id;
|
||||||
u32 creator_revision;
|
u32 creator_revision;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct [[gnu::packed]] RSDT
|
struct [[gnu::packed]] RSDT
|
||||||
{
|
{
|
||||||
SDTHeader h;
|
SDTHeader h;
|
||||||
u32 table_ptrs[];
|
u32 table_ptrs[];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct [[gnu::packed]] XSDT
|
struct [[gnu::packed]] XSDT
|
||||||
{
|
{
|
||||||
SDTHeader h;
|
SDTHeader h;
|
||||||
u64 table_ptrs[];
|
u64 table_ptrs[];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct [[gnu::packed]] GenericAddressStructure
|
struct [[gnu::packed]] GenericAddressStructure
|
||||||
{
|
{
|
||||||
u8 address_space;
|
u8 address_space;
|
||||||
u8 bit_width;
|
u8 bit_width;
|
||||||
u8 bit_offset;
|
u8 bit_offset;
|
||||||
u8 access_size;
|
u8 access_size;
|
||||||
u64 address;
|
u64 address;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct [[gnu::packed]] HPET
|
struct [[gnu::packed]] HPET
|
||||||
{
|
{
|
||||||
SDTHeader h;
|
SDTHeader h;
|
||||||
u8 hardware_revision_id;
|
u8 hardware_revision_id;
|
||||||
u8 attributes;
|
u8 attributes;
|
||||||
u16 pci_vendor_id;
|
u16 pci_vendor_id;
|
||||||
GenericAddressStructure event_timer_block;
|
GenericAddressStructure event_timer_block;
|
||||||
u8 hpet_number;
|
u8 hpet_number;
|
||||||
u16 mininum_clock_tick;
|
u16 mininum_clock_tick;
|
||||||
u8 page_protection;
|
u8 page_protection;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct [[gnu::packed]] FADT
|
struct [[gnu::packed]] FADT
|
||||||
{
|
{
|
||||||
SDTHeader h;
|
SDTHeader h;
|
||||||
u32 firmware_ctrl;
|
u32 firmware_ctrl;
|
||||||
u32 dsdt_ptr;
|
u32 dsdt_ptr;
|
||||||
u8 reserved;
|
u8 reserved;
|
||||||
u8 preferred_pm_profile;
|
u8 preferred_pm_profile;
|
||||||
u16 sci_int;
|
u16 sci_int;
|
||||||
u32 smi_cmd;
|
u32 smi_cmd;
|
||||||
u8 acpi_enable_value;
|
u8 acpi_enable_value;
|
||||||
u8 acpi_disable_value;
|
u8 acpi_disable_value;
|
||||||
u8 s4bios_req;
|
u8 s4bios_req;
|
||||||
u8 pstate_cnt;
|
u8 pstate_cnt;
|
||||||
u32 PM1a_EVT_BLK;
|
u32 PM1a_EVT_BLK;
|
||||||
u32 PM1b_EVT_BLK;
|
u32 PM1b_EVT_BLK;
|
||||||
u32 PM1a_CNT_BLK;
|
u32 PM1a_CNT_BLK;
|
||||||
u32 PM1b_CNT_BLK;
|
u32 PM1b_CNT_BLK;
|
||||||
u32 PM2_CNT_BLK;
|
u32 PM2_CNT_BLK;
|
||||||
u32 PM_TMR_BLK;
|
u32 PM_TMR_BLK;
|
||||||
u32 GPE0_BLK;
|
u32 GPE0_BLK;
|
||||||
u32 GPE1_BLK;
|
u32 GPE1_BLK;
|
||||||
u8 PM1_EVT_LEN;
|
u8 PM1_EVT_LEN;
|
||||||
u8 PM1_CNT_LEN;
|
u8 PM1_CNT_LEN;
|
||||||
u8 PM2_CNT_LEN;
|
u8 PM2_CNT_LEN;
|
||||||
u8 PM_TMR_LEN;
|
u8 PM_TMR_LEN;
|
||||||
u8 GPE0_BLK_LEN;
|
u8 GPE0_BLK_LEN;
|
||||||
u8 GPE1_BLK_LEN;
|
u8 GPE1_BLK_LEN;
|
||||||
u8 GPE1_BASE;
|
u8 GPE1_BASE;
|
||||||
u8 cst_cnt;
|
u8 cst_cnt;
|
||||||
u16 P_LVL2_LAT;
|
u16 P_LVL2_LAT;
|
||||||
u16 P_LVL3_LAT;
|
u16 P_LVL3_LAT;
|
||||||
u16 flush_size;
|
u16 flush_size;
|
||||||
u16 flush_stride;
|
u16 flush_stride;
|
||||||
u8 duty_offset;
|
u8 duty_offset;
|
||||||
u8 duty_width;
|
u8 duty_width;
|
||||||
u8 day_alrm;
|
u8 day_alrm;
|
||||||
u8 mon_alrm;
|
u8 mon_alrm;
|
||||||
u8 century;
|
u8 century;
|
||||||
u16 ia_pc_boot_arch_flags;
|
u16 ia_pc_boot_arch_flags;
|
||||||
u8 reserved2;
|
u8 reserved2;
|
||||||
u32 flags;
|
u32 flags;
|
||||||
GenericAddressStructure reset_reg;
|
GenericAddressStructure reset_reg;
|
||||||
u8 reset_value;
|
u8 reset_value;
|
||||||
u16 arm_boot_arch;
|
u16 arm_boot_arch;
|
||||||
u8 fadt_minor_version;
|
u8 fadt_minor_version;
|
||||||
u64 x_firmware_ctrl;
|
u64 x_firmware_ctrl;
|
||||||
u64 x_dsdt;
|
u64 x_dsdt;
|
||||||
GenericAddressStructure x_pm1a_evt_blk;
|
GenericAddressStructure x_pm1a_evt_blk;
|
||||||
GenericAddressStructure x_pm1b_evt_blk;
|
GenericAddressStructure x_pm1b_evt_blk;
|
||||||
GenericAddressStructure x_pm1a_cnt_blk;
|
GenericAddressStructure x_pm1a_cnt_blk;
|
||||||
GenericAddressStructure x_pm1b_cnt_blk;
|
GenericAddressStructure x_pm1b_cnt_blk;
|
||||||
GenericAddressStructure x_pm2_cnt_blk;
|
GenericAddressStructure x_pm2_cnt_blk;
|
||||||
GenericAddressStructure x_pm_tmr_blk;
|
GenericAddressStructure x_pm_tmr_blk;
|
||||||
GenericAddressStructure x_gpe0_blk;
|
GenericAddressStructure x_gpe0_blk;
|
||||||
GenericAddressStructure x_gpe1_blk;
|
GenericAddressStructure x_gpe1_blk;
|
||||||
GenericAddressStructure sleep_control;
|
GenericAddressStructure sleep_control;
|
||||||
GenericAddressStructure sleep_status;
|
GenericAddressStructure sleep_status;
|
||||||
u64 hypervisor_vendor_identity;
|
u64 hypervisor_vendor_identity;
|
||||||
};
|
};
|
||||||
enum class MADTEntryType {
|
enum class MADTEntryType {
|
||||||
LocalAPIC = 0x0,
|
LocalAPIC = 0x0,
|
||||||
IOAPIC = 0x1,
|
IOAPIC = 0x1,
|
||||||
InterruptSourceOverride = 0x2,
|
InterruptSourceOverride = 0x2,
|
||||||
NMI_Source = 0x3,
|
NMI_Source = 0x3,
|
||||||
LocalAPIC_NMI = 0x4,
|
LocalAPIC_NMI = 0x4,
|
||||||
LocalAPIC_Address_Override = 0x5,
|
LocalAPIC_Address_Override = 0x5,
|
||||||
IO_SAPIC = 0x6,
|
IO_SAPIC = 0x6,
|
||||||
Local_SAPIC = 0x7,
|
Local_SAPIC = 0x7,
|
||||||
Platform_interrupt_Sources = 0x8,
|
Platform_interrupt_Sources = 0x8,
|
||||||
Local_x2APIC = 0x9,
|
Local_x2APIC = 0x9,
|
||||||
Local_x2APIC_NMI = 0xA,
|
Local_x2APIC_NMI = 0xA,
|
||||||
GIC_CPU = 0xB,
|
GIC_CPU = 0xB,
|
||||||
GIC_Distributor = 0xC,
|
GIC_Distributor = 0xC,
|
||||||
GIC_MSI = 0xD,
|
GIC_MSI = 0xD,
|
||||||
GIC_Redistrbutor = 0xE,
|
GIC_Redistrbutor = 0xE,
|
||||||
GIC_Interrupt_Translation = 0xF
|
GIC_Interrupt_Translation = 0xF
|
||||||
};
|
};
|
||||||
|
|
||||||
struct [[gnu::packed]] MADTEntryHeader
|
struct [[gnu::packed]] MADTEntryHeader
|
||||||
{
|
{
|
||||||
u8 type;
|
u8 type;
|
||||||
u8 length;
|
u8 length;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace MADTEntries {
|
namespace MADTEntries {
|
||||||
struct [[gnu::packed]] IOAPIC
|
struct [[gnu::packed]] IOAPIC
|
||||||
{
|
{
|
||||||
MADTEntryHeader h;
|
MADTEntryHeader h;
|
||||||
u8 ioapic_id;
|
u8 ioapic_id;
|
||||||
u8 reserved;
|
u8 reserved;
|
||||||
u32 ioapic_address;
|
u32 ioapic_address;
|
||||||
u32 gsi_base;
|
u32 gsi_base;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct [[gnu::packed]] InterruptSourceOverride
|
struct [[gnu::packed]] InterruptSourceOverride
|
||||||
{
|
{
|
||||||
MADTEntryHeader h;
|
MADTEntryHeader h;
|
||||||
u8 bus;
|
u8 bus;
|
||||||
u8 source;
|
u8 source;
|
||||||
u32 global_system_interrupt;
|
u32 global_system_interrupt;
|
||||||
u16 flags;
|
u16 flags;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
struct [[gnu::packed]] MADT
|
struct [[gnu::packed]] MADT
|
||||||
{
|
{
|
||||||
SDTHeader h;
|
SDTHeader h;
|
||||||
u32 lapic_address;
|
u32 lapic_address;
|
||||||
u32 flags;
|
u32 flags;
|
||||||
MADTEntryHeader entries[];
|
MADTEntryHeader entries[];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct [[gnu::packed]] AMLTable
|
struct [[gnu::packed]] AMLTable
|
||||||
{
|
{
|
||||||
SDTHeader h;
|
SDTHeader h;
|
||||||
char aml_code[];
|
char aml_code[];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct [[gnu::packed]] PCI_MMIO_Descriptor
|
struct [[gnu::packed]] PCI_MMIO_Descriptor
|
||||||
{
|
{
|
||||||
u64 base_addr;
|
u64 base_addr;
|
||||||
u16 seg_group_number;
|
u16 seg_group_number;
|
||||||
u8 start_pci_bus;
|
u8 start_pci_bus;
|
||||||
u8 end_pci_bus;
|
u8 end_pci_bus;
|
||||||
u32 reserved;
|
u32 reserved;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct [[gnu::packed]] MCFG
|
struct [[gnu::packed]] MCFG
|
||||||
{
|
{
|
||||||
SDTHeader header;
|
SDTHeader header;
|
||||||
u64 reserved;
|
u64 reserved;
|
||||||
PCI_MMIO_Descriptor descriptors[];
|
PCI_MMIO_Descriptor descriptors[];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
class StaticParser;
|
class StaticParser;
|
||||||
class DynamicParser;
|
class DynamicParser;
|
||||||
class Parser;
|
class Parser;
|
||||||
|
|
||||||
namespace StaticParsing {
|
namespace StaticParsing {
|
||||||
PhysicalAddress search_rsdp_in_ebda(u16 ebda_segment);
|
PhysicalAddress search_rsdp_in_ebda(u16 ebda_segment);
|
||||||
PhysicalAddress search_rsdp_in_bios_area();
|
PhysicalAddress search_rsdp_in_bios_area();
|
||||||
PhysicalAddress search_rsdp();
|
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);
|
inline bool validate_table(Structures::SDTHeader&, size_t length);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,156 +34,156 @@
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
namespace MultiProcessor {
|
namespace MultiProcessor {
|
||||||
|
|
||||||
struct [[gnu::packed]] FloatingPointer
|
struct [[gnu::packed]] FloatingPointer
|
||||||
{
|
{
|
||||||
char sig[4];
|
char sig[4];
|
||||||
u32 physical_address_ptr;
|
u32 physical_address_ptr;
|
||||||
u8 length;
|
u8 length;
|
||||||
u8 specification_revision;
|
u8 specification_revision;
|
||||||
u8 checksum;
|
u8 checksum;
|
||||||
u8 feature_info[5];
|
u8 feature_info[5];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct [[gnu::packed]] EntryHeader
|
struct [[gnu::packed]] EntryHeader
|
||||||
{
|
{
|
||||||
u8 entry_type;
|
u8 entry_type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct [[gnu::packed]] ConfigurationTableHeader
|
struct [[gnu::packed]] ConfigurationTableHeader
|
||||||
{
|
{
|
||||||
char sig[4];
|
char sig[4];
|
||||||
u16 length;
|
u16 length;
|
||||||
u8 specification_revision;
|
u8 specification_revision;
|
||||||
u8 checksum;
|
u8 checksum;
|
||||||
char oem_id[8];
|
char oem_id[8];
|
||||||
char product_id[12];
|
char product_id[12];
|
||||||
u32 oem_table_ptr;
|
u32 oem_table_ptr;
|
||||||
u16 oem_table_size;
|
u16 oem_table_size;
|
||||||
u16 entry_count;
|
u16 entry_count;
|
||||||
u32 local_apic_address;
|
u32 local_apic_address;
|
||||||
u16 ext_table_length;
|
u16 ext_table_length;
|
||||||
u8 ext_table_checksum;
|
u8 ext_table_checksum;
|
||||||
u8 reserved;
|
u8 reserved;
|
||||||
EntryHeader entries[];
|
EntryHeader entries[];
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ConfigurationTableEntryType {
|
enum class ConfigurationTableEntryType {
|
||||||
Processor = 0,
|
Processor = 0,
|
||||||
Bus = 1,
|
Bus = 1,
|
||||||
IOAPIC = 2,
|
IOAPIC = 2,
|
||||||
IO_Interrupt_Assignment = 3,
|
IO_Interrupt_Assignment = 3,
|
||||||
Local_Interrupt_Assignment = 4,
|
Local_Interrupt_Assignment = 4,
|
||||||
SystemAddressSpaceMapping = 128,
|
SystemAddressSpaceMapping = 128,
|
||||||
BusHierarchyDescriptor = 129,
|
BusHierarchyDescriptor = 129,
|
||||||
CompatibilityBusAddressSpaceModifier = 130
|
CompatibilityBusAddressSpaceModifier = 130
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class ConfigurationTableEntryLength {
|
enum class ConfigurationTableEntryLength {
|
||||||
Processor = 20,
|
Processor = 20,
|
||||||
Bus = 8,
|
Bus = 8,
|
||||||
IOAPIC = 8,
|
IOAPIC = 8,
|
||||||
IO_Interrupt_Assignment = 8,
|
IO_Interrupt_Assignment = 8,
|
||||||
Local_Interrupt_Assignment = 8,
|
Local_Interrupt_Assignment = 8,
|
||||||
SystemAddressSpaceMapping = 20,
|
SystemAddressSpaceMapping = 20,
|
||||||
BusHierarchyDescriptor = 8,
|
BusHierarchyDescriptor = 8,
|
||||||
CompatibilityBusAddressSpaceModifier = 8
|
CompatibilityBusAddressSpaceModifier = 8
|
||||||
};
|
};
|
||||||
|
|
||||||
struct [[gnu::packed]] ExtEntryHeader
|
struct [[gnu::packed]] ExtEntryHeader
|
||||||
{
|
{
|
||||||
u8 entry_type;
|
u8 entry_type;
|
||||||
u8 entry_length;
|
u8 entry_length;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct [[gnu::packed]] ProcessorEntry
|
struct [[gnu::packed]] ProcessorEntry
|
||||||
{
|
{
|
||||||
EntryHeader h;
|
EntryHeader h;
|
||||||
u8 local_apic_id;
|
u8 local_apic_id;
|
||||||
u8 local_apic_version;
|
u8 local_apic_version;
|
||||||
u8 cpu_flags;
|
u8 cpu_flags;
|
||||||
u32 cpu_signature;
|
u32 cpu_signature;
|
||||||
u32 feature_flags;
|
u32 feature_flags;
|
||||||
u8 reserved[8];
|
u8 reserved[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct [[gnu::packed]] BusEntry
|
struct [[gnu::packed]] BusEntry
|
||||||
{
|
{
|
||||||
EntryHeader h;
|
EntryHeader h;
|
||||||
u8 bus_id;
|
u8 bus_id;
|
||||||
char bus_type[6];
|
char bus_type[6];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct [[gnu::packed]] IOAPICEntry
|
struct [[gnu::packed]] IOAPICEntry
|
||||||
{
|
{
|
||||||
EntryHeader h;
|
EntryHeader h;
|
||||||
u8 ioapic_id;
|
u8 ioapic_id;
|
||||||
u8 ioapic_version;
|
u8 ioapic_version;
|
||||||
u8 ioapic_flags;
|
u8 ioapic_flags;
|
||||||
u32 ioapic_address;
|
u32 ioapic_address;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class InterruptType {
|
enum class InterruptType {
|
||||||
INT = 0,
|
INT = 0,
|
||||||
NMI = 1,
|
NMI = 1,
|
||||||
SMI = 2,
|
SMI = 2,
|
||||||
ExtINT = 3,
|
ExtINT = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct [[gnu::packed]] IOInterruptAssignmentEntry
|
struct [[gnu::packed]] IOInterruptAssignmentEntry
|
||||||
{
|
{
|
||||||
EntryHeader h;
|
EntryHeader h;
|
||||||
u8 interrupt_type;
|
u8 interrupt_type;
|
||||||
u8 polarity;
|
u8 polarity;
|
||||||
u8 trigger_mode;
|
u8 trigger_mode;
|
||||||
u8 source_bus_id;
|
u8 source_bus_id;
|
||||||
u8 source_bus_irq;
|
u8 source_bus_irq;
|
||||||
u8 destination_ioapic_id;
|
u8 destination_ioapic_id;
|
||||||
u8 destination_ioapic_intin_pin;
|
u8 destination_ioapic_intin_pin;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct [[gnu::packed]] LocalInterruptAssignmentEntry
|
struct [[gnu::packed]] LocalInterruptAssignmentEntry
|
||||||
{
|
{
|
||||||
EntryHeader h;
|
EntryHeader h;
|
||||||
u8 interrupt_type;
|
u8 interrupt_type;
|
||||||
u8 polarity;
|
u8 polarity;
|
||||||
u8 trigger_mode;
|
u8 trigger_mode;
|
||||||
u8 source_bus_id;
|
u8 source_bus_id;
|
||||||
u8 source_bus_irq;
|
u8 source_bus_irq;
|
||||||
u8 destination_lapic_id;
|
u8 destination_lapic_id;
|
||||||
u8 destination_lapic_lintin_pin;
|
u8 destination_lapic_lintin_pin;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class SystemAddressType {
|
enum class SystemAddressType {
|
||||||
IO = 0,
|
IO = 0,
|
||||||
Memory = 1,
|
Memory = 1,
|
||||||
Prefetch = 2,
|
Prefetch = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct [[gnu::packed]] SystemAddressSpaceMappingEntry
|
struct [[gnu::packed]] SystemAddressSpaceMappingEntry
|
||||||
{
|
{
|
||||||
ExtEntryHeader h;
|
ExtEntryHeader h;
|
||||||
u8 bus_id;
|
u8 bus_id;
|
||||||
u8 address_type;
|
u8 address_type;
|
||||||
u64 address_base;
|
u64 address_base;
|
||||||
u64 length;
|
u64 length;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct [[gnu::packed]] BusHierarchyDescriptorEntry
|
struct [[gnu::packed]] BusHierarchyDescriptorEntry
|
||||||
{
|
{
|
||||||
ExtEntryHeader h;
|
ExtEntryHeader h;
|
||||||
u8 bus_id;
|
u8 bus_id;
|
||||||
u8 bus_info;
|
u8 bus_info;
|
||||||
u8 parent_bus;
|
u8 parent_bus;
|
||||||
u8 reserved[3];
|
u8 reserved[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct [[gnu::packed]] CompatibilityBusAddressSpaceModifierEntry
|
struct [[gnu::packed]] CompatibilityBusAddressSpaceModifierEntry
|
||||||
{
|
{
|
||||||
ExtEntryHeader h;
|
ExtEntryHeader h;
|
||||||
u8 bus_id;
|
u8 bus_id;
|
||||||
u8 address_modifier;
|
u8 address_modifier;
|
||||||
u32 predefined_range_list;
|
u32 predefined_range_list;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -261,10 +261,10 @@ void page_fault_handler(RegisterState regs)
|
||||||
}
|
}
|
||||||
|
|
||||||
dbg() << "Unrecoverable page fault, "
|
dbg() << "Unrecoverable page fault, "
|
||||||
<< (regs.exception_code & PageFaultFlags::ReservedBitViolation ? "reserved bit violation / " : "")
|
<< (regs.exception_code & PageFaultFlags::ReservedBitViolation ? "reserved bit violation / " : "")
|
||||||
<< (regs.exception_code & PageFaultFlags::InstructionFetch ? "instruction fetch / " : "")
|
<< (regs.exception_code & PageFaultFlags::InstructionFetch ? "instruction fetch / " : "")
|
||||||
<< (regs.exception_code & PageFaultFlags::Write ? "write to" : "read from")
|
<< (regs.exception_code & PageFaultFlags::Write ? "write to" : "read from")
|
||||||
<< " address " << VirtualAddress(fault_address);
|
<< " address " << VirtualAddress(fault_address);
|
||||||
u32 malloc_scrub_pattern = explode_byte(MALLOC_SCRUB_BYTE);
|
u32 malloc_scrub_pattern = explode_byte(MALLOC_SCRUB_BYTE);
|
||||||
u32 free_scrub_pattern = explode_byte(FREE_SCRUB_BYTE);
|
u32 free_scrub_pattern = explode_byte(FREE_SCRUB_BYTE);
|
||||||
u32 kmalloc_scrub_pattern = explode_byte(KMALLOC_SCRUB_BYTE);
|
u32 kmalloc_scrub_pattern = explode_byte(KMALLOC_SCRUB_BYTE);
|
||||||
|
|
|
@ -329,7 +329,6 @@ Optional<KBuffer> procfs$pid_vm(InodeIdentifier identifier)
|
||||||
pagemap_builder.append('P');
|
pagemap_builder.append('P');
|
||||||
}
|
}
|
||||||
region_object.add("pagemap", pagemap_builder.to_string());
|
region_object.add("pagemap", pagemap_builder.to_string());
|
||||||
|
|
||||||
}
|
}
|
||||||
array.finish();
|
array.finish();
|
||||||
return builder.build();
|
return builder.build();
|
||||||
|
|
|
@ -54,177 +54,177 @@ namespace Kernel {
|
||||||
|
|
||||||
namespace APIC {
|
namespace APIC {
|
||||||
|
|
||||||
class ICRReg {
|
class ICRReg {
|
||||||
u32 m_reg { 0 };
|
u32 m_reg { 0 };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum DeliveryMode {
|
enum DeliveryMode {
|
||||||
Fixed = 0x0,
|
Fixed = 0x0,
|
||||||
LowPriority = 0x1,
|
LowPriority = 0x1,
|
||||||
SMI = 0x2,
|
SMI = 0x2,
|
||||||
NMI = 0x4,
|
NMI = 0x4,
|
||||||
INIT = 0x5,
|
INIT = 0x5,
|
||||||
StartUp = 0x6,
|
StartUp = 0x6,
|
||||||
};
|
};
|
||||||
enum DestinationMode {
|
enum DestinationMode {
|
||||||
Physical = 0x0,
|
Physical = 0x0,
|
||||||
Logical = 0x0,
|
Logical = 0x0,
|
||||||
};
|
};
|
||||||
enum Level {
|
enum Level {
|
||||||
DeAssert = 0x0,
|
DeAssert = 0x0,
|
||||||
Assert = 0x1
|
Assert = 0x1
|
||||||
};
|
};
|
||||||
enum class TriggerMode {
|
enum class TriggerMode {
|
||||||
Edge = 0x0,
|
Edge = 0x0,
|
||||||
Level = 0x1,
|
Level = 0x1,
|
||||||
};
|
};
|
||||||
enum DestinationShorthand {
|
enum DestinationShorthand {
|
||||||
NoShorthand = 0x0,
|
NoShorthand = 0x0,
|
||||||
Self = 0x1,
|
Self = 0x1,
|
||||||
AllIncludingSelf = 0x2,
|
AllIncludingSelf = 0x2,
|
||||||
AllExcludingSelf = 0x3,
|
AllExcludingSelf = 0x3,
|
||||||
};
|
|
||||||
|
|
||||||
ICRReg(u8 vector, DeliveryMode delivery_mode, DestinationMode destination_mode, Level level, TriggerMode trigger_mode, DestinationShorthand destination)
|
|
||||||
: m_reg(vector | (delivery_mode << 8) | (destination_mode << 11) | (level << 14) | (static_cast<u32>(trigger_mode) << 15) | (destination << 18))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 low() const { return m_reg; }
|
|
||||||
u32 high() const { return 0; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static volatile u8* g_apic_base = nullptr;
|
ICRReg(u8 vector, DeliveryMode delivery_mode, DestinationMode destination_mode, Level level, TriggerMode trigger_mode, DestinationShorthand destination)
|
||||||
|
: m_reg(vector | (delivery_mode << 8) | (destination_mode << 11) | (level << 14) | (static_cast<u32>(trigger_mode) << 15) | (destination << 18))
|
||||||
static PhysicalAddress get_base()
|
|
||||||
{
|
{
|
||||||
u32 lo, hi;
|
|
||||||
MSR msr(APIC_BASE_MSR);
|
|
||||||
msr.get(lo, hi);
|
|
||||||
return PhysicalAddress(lo & 0xfffff000);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_base(const PhysicalAddress& base)
|
u32 low() const { return m_reg; }
|
||||||
{
|
u32 high() const { return 0; }
|
||||||
u32 hi = 0;
|
};
|
||||||
u32 lo = base.get() | 0x800;
|
|
||||||
MSR msr(APIC_BASE_MSR);
|
|
||||||
msr.set(lo, hi);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void write_register(u32 offset, u32 value)
|
static volatile u8* g_apic_base = nullptr;
|
||||||
{
|
|
||||||
auto lapic_region = MM.allocate_kernel_region(PhysicalAddress(page_base_of((u32)g_apic_base)), PAGE_SIZE, "LAPIC Write Access", Region::Access::Read | Region::Access::Write, false, true);
|
|
||||||
auto* lapic = (volatile u32*)lapic_region->vaddr().offset(offset_in_page((u32)g_apic_base)).offset(offset).as_ptr();
|
|
||||||
*lapic = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
static u32 read_register(u32 offset)
|
static PhysicalAddress get_base()
|
||||||
{
|
{
|
||||||
auto lapic_region = MM.allocate_kernel_region(PhysicalAddress(page_base_of((u32)g_apic_base)), PAGE_SIZE, "LAPIC Read Access", Region::Access::Read, false, true);
|
u32 lo, hi;
|
||||||
auto* lapic = (volatile u32*)lapic_region->vaddr().offset(offset_in_page((u32)g_apic_base)).offset(offset).as_ptr();
|
MSR msr(APIC_BASE_MSR);
|
||||||
return *lapic;
|
msr.get(lo, hi);
|
||||||
}
|
return PhysicalAddress(lo & 0xfffff000);
|
||||||
|
}
|
||||||
|
|
||||||
static void write_icr(const ICRReg& icr)
|
static void set_base(const PhysicalAddress& base)
|
||||||
{
|
{
|
||||||
write_register(APIC_REG_ICR_HIGH, icr.high());
|
u32 hi = 0;
|
||||||
write_register(APIC_REG_ICR_LOW, icr.low());
|
u32 lo = base.get() | 0x800;
|
||||||
}
|
MSR msr(APIC_BASE_MSR);
|
||||||
|
msr.set(lo, hi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_register(u32 offset, u32 value)
|
||||||
|
{
|
||||||
|
auto lapic_region = MM.allocate_kernel_region(PhysicalAddress(page_base_of((u32)g_apic_base)), PAGE_SIZE, "LAPIC Write Access", Region::Access::Read | Region::Access::Write, false, true);
|
||||||
|
auto* lapic = (volatile u32*)lapic_region->vaddr().offset(offset_in_page((u32)g_apic_base)).offset(offset).as_ptr();
|
||||||
|
*lapic = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u32 read_register(u32 offset)
|
||||||
|
{
|
||||||
|
auto lapic_region = MM.allocate_kernel_region(PhysicalAddress(page_base_of((u32)g_apic_base)), PAGE_SIZE, "LAPIC Read Access", Region::Access::Read, false, true);
|
||||||
|
auto* lapic = (volatile u32*)lapic_region->vaddr().offset(offset_in_page((u32)g_apic_base)).offset(offset).as_ptr();
|
||||||
|
return *lapic;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write_icr(const ICRReg& icr)
|
||||||
|
{
|
||||||
|
write_register(APIC_REG_ICR_HIGH, icr.high());
|
||||||
|
write_register(APIC_REG_ICR_LOW, icr.low());
|
||||||
|
}
|
||||||
|
|
||||||
#define APIC_LVT_MASKED (1 << 16)
|
#define APIC_LVT_MASKED (1 << 16)
|
||||||
#define APIC_LVT_TRIGGER_LEVEL (1 << 14)
|
#define APIC_LVT_TRIGGER_LEVEL (1 << 14)
|
||||||
#define APIC_LVT(iv, dm) ((iv & 0xff) | ((dm & 0x7) << 8))
|
#define APIC_LVT(iv, dm) ((iv & 0xff) | ((dm & 0x7) << 8))
|
||||||
|
|
||||||
asm(
|
asm(
|
||||||
".globl apic_ap_start \n"
|
".globl apic_ap_start \n"
|
||||||
".type apic_ap_start, @function \n"
|
".type apic_ap_start, @function \n"
|
||||||
"apic_ap_start: \n"
|
"apic_ap_start: \n"
|
||||||
".set begin_apic_ap_start, . \n"
|
".set begin_apic_ap_start, . \n"
|
||||||
" jmp apic_ap_start\n" // TODO: implement
|
" jmp apic_ap_start\n" // TODO: implement
|
||||||
".set end_apic_ap_start, . \n"
|
".set end_apic_ap_start, . \n"
|
||||||
"\n"
|
"\n"
|
||||||
".globl apic_ap_start_size \n"
|
".globl apic_ap_start_size \n"
|
||||||
"apic_ap_start_size: \n"
|
"apic_ap_start_size: \n"
|
||||||
".word end_apic_ap_start - begin_apic_ap_start \n");
|
".word end_apic_ap_start - begin_apic_ap_start \n");
|
||||||
|
|
||||||
extern "C" void apic_ap_start(void);
|
extern "C" void apic_ap_start(void);
|
||||||
extern "C" u16 apic_ap_start_size;
|
extern "C" u16 apic_ap_start_size;
|
||||||
|
|
||||||
void eoi()
|
void eoi()
|
||||||
{
|
{
|
||||||
write_register(APIC_REG_EOI, 0x0);
|
write_register(APIC_REG_EOI, 0x0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool init()
|
bool init()
|
||||||
{
|
{
|
||||||
if (!MSR::have())
|
if (!MSR::have())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// check if we support local apic
|
// check if we support local apic
|
||||||
CPUID id(1);
|
CPUID id(1);
|
||||||
if ((id.edx() & (1 << 9)) == 0)
|
if ((id.edx() & (1 << 9)) == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
PhysicalAddress apic_base = get_base();
|
PhysicalAddress apic_base = get_base();
|
||||||
klog() << "Initializing APIC, base: " << apic_base;
|
klog() << "Initializing APIC, base: " << apic_base;
|
||||||
set_base(apic_base);
|
set_base(apic_base);
|
||||||
|
|
||||||
g_apic_base = apic_base.as_ptr();
|
g_apic_base = apic_base.as_ptr();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void enable_bsp()
|
void enable_bsp()
|
||||||
{
|
{
|
||||||
// FIXME: Ensure this method can only be executed by the BSP.
|
// FIXME: Ensure this method can only be executed by the BSP.
|
||||||
enable(0);
|
enable(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void enable(u32 cpu)
|
void enable(u32 cpu)
|
||||||
{
|
{
|
||||||
klog() << "Enabling local APIC for cpu #" << cpu;
|
klog() << "Enabling local APIC for cpu #" << cpu;
|
||||||
|
|
||||||
// dummy read, apparently to avoid a bug in old CPUs.
|
// dummy read, apparently to avoid a bug in old CPUs.
|
||||||
read_register(APIC_REG_SIV);
|
read_register(APIC_REG_SIV);
|
||||||
// set spurious interrupt vector
|
// set spurious interrupt vector
|
||||||
write_register(APIC_REG_SIV, IRQ_APIC_SPURIOUS | 0x100);
|
write_register(APIC_REG_SIV, IRQ_APIC_SPURIOUS | 0x100);
|
||||||
|
|
||||||
// local destination mode (flat mode)
|
// local destination mode (flat mode)
|
||||||
write_register(APIC_REG_DF, 0xf0000000);
|
write_register(APIC_REG_DF, 0xf0000000);
|
||||||
|
|
||||||
// set destination id (note that this limits it to 8 cpus)
|
// set destination id (note that this limits it to 8 cpus)
|
||||||
write_register(APIC_REG_LD, 0);
|
write_register(APIC_REG_LD, 0);
|
||||||
|
|
||||||
SpuriousInterruptHandler::initialize(IRQ_APIC_SPURIOUS);
|
SpuriousInterruptHandler::initialize(IRQ_APIC_SPURIOUS);
|
||||||
|
|
||||||
write_register(APIC_REG_LVT_TIMER, APIC_LVT(0, 0) | APIC_LVT_MASKED);
|
write_register(APIC_REG_LVT_TIMER, APIC_LVT(0, 0) | APIC_LVT_MASKED);
|
||||||
write_register(APIC_REG_LVT_THERMAL, APIC_LVT(0, 0) | APIC_LVT_MASKED);
|
write_register(APIC_REG_LVT_THERMAL, APIC_LVT(0, 0) | APIC_LVT_MASKED);
|
||||||
write_register(APIC_REG_LVT_PERFORMANCE_COUNTER, APIC_LVT(0, 0) | APIC_LVT_MASKED);
|
write_register(APIC_REG_LVT_PERFORMANCE_COUNTER, APIC_LVT(0, 0) | APIC_LVT_MASKED);
|
||||||
write_register(APIC_REG_LVT_LINT0, APIC_LVT(0, 7) | APIC_LVT_MASKED);
|
write_register(APIC_REG_LVT_LINT0, APIC_LVT(0, 7) | APIC_LVT_MASKED);
|
||||||
write_register(APIC_REG_LVT_LINT1, APIC_LVT(0, 0) | APIC_LVT_TRIGGER_LEVEL);
|
write_register(APIC_REG_LVT_LINT1, APIC_LVT(0, 0) | APIC_LVT_TRIGGER_LEVEL);
|
||||||
write_register(APIC_REG_LVT_ERR, APIC_LVT(0, 0) | APIC_LVT_MASKED);
|
write_register(APIC_REG_LVT_ERR, APIC_LVT(0, 0) | APIC_LVT_MASKED);
|
||||||
|
|
||||||
write_register(APIC_REG_TPR, 0);
|
write_register(APIC_REG_TPR, 0);
|
||||||
|
|
||||||
if (cpu != 0) {
|
if (cpu != 0) {
|
||||||
static volatile u32 foo = 0;
|
static volatile u32 foo = 0;
|
||||||
|
|
||||||
// INIT
|
// INIT
|
||||||
write_icr(ICRReg(0, ICRReg::INIT, ICRReg::Physical, ICRReg::Assert, ICRReg::TriggerMode::Edge, ICRReg::AllExcludingSelf));
|
write_icr(ICRReg(0, ICRReg::INIT, ICRReg::Physical, ICRReg::Assert, ICRReg::TriggerMode::Edge, ICRReg::AllExcludingSelf));
|
||||||
|
|
||||||
for (foo = 0; foo < 0x800000; foo++)
|
for (foo = 0; foo < 0x800000; foo++)
|
||||||
; // TODO: 10 millisecond delay
|
; // TODO: 10 millisecond delay
|
||||||
|
|
||||||
for (int i = 0; i < 2; i++) {
|
for (int i = 0; i < 2; i++) {
|
||||||
// SIPI
|
// SIPI
|
||||||
write_icr(ICRReg(0x08, ICRReg::StartUp, ICRReg::Physical, ICRReg::Assert, ICRReg::TriggerMode::Edge, ICRReg::AllExcludingSelf)); // start execution at P8000
|
write_icr(ICRReg(0x08, ICRReg::StartUp, ICRReg::Physical, ICRReg::Assert, ICRReg::TriggerMode::Edge, ICRReg::AllExcludingSelf)); // start execution at P8000
|
||||||
|
|
||||||
for (foo = 0; foo < 0x80000; foo++)
|
for (foo = 0; foo < 0x80000; foo++)
|
||||||
; // TODO: 200 microsecond delay
|
; // TODO: 200 microsecond delay
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,10 +32,10 @@ namespace Kernel {
|
||||||
|
|
||||||
namespace APIC {
|
namespace APIC {
|
||||||
|
|
||||||
void enable_bsp();
|
void enable_bsp();
|
||||||
void eoi();
|
void eoi();
|
||||||
bool init();
|
bool init();
|
||||||
void enable(u32 cpu);
|
void enable(u32 cpu);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,8 +30,8 @@
|
||||||
#include <AK/OwnPtr.h>
|
#include <AK/OwnPtr.h>
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
#include <Kernel/Arch/i386/CPU.h>
|
#include <Kernel/Arch/i386/CPU.h>
|
||||||
#include <Kernel/Interrupts/IRQController.h>
|
|
||||||
#include <Kernel/Interrupts/GenericInterruptHandler.h>
|
#include <Kernel/Interrupts/GenericInterruptHandler.h>
|
||||||
|
#include <Kernel/Interrupts/IRQController.h>
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
|
|
|
@ -26,8 +26,8 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <AK/String.h>
|
|
||||||
#include <AK/HashMap.h>
|
#include <AK/HashMap.h>
|
||||||
|
#include <AK/String.h>
|
||||||
|
|
||||||
class KParams {
|
class KParams {
|
||||||
AK_MAKE_ETERNAL
|
AK_MAKE_ETERNAL
|
||||||
|
|
|
@ -29,9 +29,9 @@
|
||||||
#include <AK/OwnPtr.h>
|
#include <AK/OwnPtr.h>
|
||||||
#include <Kernel/Interrupts/IRQHandler.h>
|
#include <Kernel/Interrupts/IRQHandler.h>
|
||||||
#include <Kernel/Net/NetworkAdapter.h>
|
#include <Kernel/Net/NetworkAdapter.h>
|
||||||
#include <LibBareMetal/IO.h>
|
|
||||||
#include <Kernel/PCI/Access.h>
|
#include <Kernel/PCI/Access.h>
|
||||||
#include <Kernel/PCI/Device.h>
|
#include <Kernel/PCI/Device.h>
|
||||||
|
#include <LibBareMetal/IO.h>
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
|
|
|
@ -26,10 +26,10 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <AK/String.h>
|
|
||||||
#include <AK/Assertions.h>
|
#include <AK/Assertions.h>
|
||||||
#include <AK/IPv4Address.h>
|
#include <AK/IPv4Address.h>
|
||||||
#include <AK/NetworkOrdered.h>
|
#include <AK/NetworkOrdered.h>
|
||||||
|
#include <AK/String.h>
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
|
@ -30,8 +30,8 @@
|
||||||
#include <AK/Function.h>
|
#include <AK/Function.h>
|
||||||
#include <AK/SinglyLinkedList.h>
|
#include <AK/SinglyLinkedList.h>
|
||||||
#include <AK/Types.h>
|
#include <AK/Types.h>
|
||||||
#include <AK/Weakable.h>
|
|
||||||
#include <AK/WeakPtr.h>
|
#include <AK/WeakPtr.h>
|
||||||
|
#include <AK/Weakable.h>
|
||||||
#include <Kernel/KBuffer.h>
|
#include <Kernel/KBuffer.h>
|
||||||
#include <Kernel/Net/ARP.h>
|
#include <Kernel/Net/ARP.h>
|
||||||
#include <Kernel/Net/ICMP.h>
|
#include <Kernel/Net/ICMP.h>
|
||||||
|
|
|
@ -30,8 +30,7 @@
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
struct RoutingDecision
|
struct RoutingDecision {
|
||||||
{
|
|
||||||
RefPtr<NetworkAdapter> adapter;
|
RefPtr<NetworkAdapter> adapter;
|
||||||
MACAddress next_hop;
|
MACAddress next_hop;
|
||||||
|
|
||||||
|
|
|
@ -126,7 +126,6 @@ public:
|
||||||
virtual ssize_t write(FileDescription&, const u8*, ssize_t) override final;
|
virtual ssize_t write(FileDescription&, const u8*, ssize_t) override final;
|
||||||
virtual String absolute_path(const FileDescription&) const override = 0;
|
virtual String absolute_path(const FileDescription&) const override = 0;
|
||||||
|
|
||||||
|
|
||||||
bool has_receive_timeout() const { return m_receive_timeout.tv_sec || m_receive_timeout.tv_usec; }
|
bool has_receive_timeout() const { return m_receive_timeout.tv_sec || m_receive_timeout.tv_usec; }
|
||||||
const timeval& receive_timeout() const { return m_receive_timeout; }
|
const timeval& receive_timeout() const { return m_receive_timeout; }
|
||||||
|
|
||||||
|
|
|
@ -108,103 +108,103 @@ void PCI::Access::disable_bus_mastering(Address address)
|
||||||
|
|
||||||
namespace PCI {
|
namespace PCI {
|
||||||
|
|
||||||
void enumerate_all(Function<void(Address, ID)> callback)
|
void enumerate_all(Function<void(Address, ID)> callback)
|
||||||
{
|
{
|
||||||
PCI::Access::the().enumerate_all(callback);
|
PCI::Access::the().enumerate_all(callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
void raw_access(Address address, u32 field, size_t access_size, u32 value)
|
void raw_access(Address address, u32 field, size_t access_size, u32 value)
|
||||||
{
|
{
|
||||||
ASSERT(access_size != 0);
|
ASSERT(access_size != 0);
|
||||||
if (access_size == 1) {
|
if (access_size == 1) {
|
||||||
PCI::Access::the().write8_field(address, field, value);
|
PCI::Access::the().write8_field(address, field, value);
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
if (access_size == 2) {
|
|
||||||
PCI::Access::the().write16_field(address, field, value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (access_size == 4) {
|
|
||||||
PCI::Access::the().write32_field(address, field, value);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
ASSERT_NOT_REACHED();
|
|
||||||
}
|
}
|
||||||
|
if (access_size == 2) {
|
||||||
|
PCI::Access::the().write16_field(address, field, value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (access_size == 4) {
|
||||||
|
PCI::Access::the().write32_field(address, field, value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ASSERT_NOT_REACHED();
|
||||||
|
}
|
||||||
|
|
||||||
ID get_id(Address address)
|
ID get_id(Address address)
|
||||||
{
|
{
|
||||||
return PCI::Access::the().get_id(address);
|
return PCI::Access::the().get_id(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
void enable_interrupt_line(Address address)
|
void enable_interrupt_line(Address address)
|
||||||
{
|
{
|
||||||
PCI::Access::the().enable_interrupt_line(address);
|
PCI::Access::the().enable_interrupt_line(address);
|
||||||
}
|
}
|
||||||
void disable_interrupt_line(Address address)
|
void disable_interrupt_line(Address address)
|
||||||
{
|
{
|
||||||
PCI::Access::the().disable_interrupt_line(address);
|
PCI::Access::the().disable_interrupt_line(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
u8 get_interrupt_line(Address address)
|
u8 get_interrupt_line(Address address)
|
||||||
{
|
{
|
||||||
return PCI::Access::the().get_interrupt_line(address);
|
return PCI::Access::the().get_interrupt_line(address);
|
||||||
}
|
}
|
||||||
u32 get_BAR0(Address address)
|
u32 get_BAR0(Address address)
|
||||||
{
|
{
|
||||||
return PCI::Access::the().get_BAR0(address);
|
return PCI::Access::the().get_BAR0(address);
|
||||||
}
|
}
|
||||||
u32 get_BAR1(Address address)
|
u32 get_BAR1(Address address)
|
||||||
{
|
{
|
||||||
return PCI::Access::the().get_BAR1(address);
|
return PCI::Access::the().get_BAR1(address);
|
||||||
}
|
}
|
||||||
u32 get_BAR2(Address address)
|
u32 get_BAR2(Address address)
|
||||||
{
|
{
|
||||||
return PCI::Access::the().get_BAR2(address);
|
return PCI::Access::the().get_BAR2(address);
|
||||||
}
|
}
|
||||||
u32 get_BAR3(Address address)
|
u32 get_BAR3(Address address)
|
||||||
{
|
{
|
||||||
return PCI::Access::the().get_BAR3(address);
|
return PCI::Access::the().get_BAR3(address);
|
||||||
}
|
}
|
||||||
u32 get_BAR4(Address address)
|
u32 get_BAR4(Address address)
|
||||||
{
|
{
|
||||||
return PCI::Access::the().get_BAR4(address);
|
return PCI::Access::the().get_BAR4(address);
|
||||||
}
|
}
|
||||||
u32 get_BAR5(Address address)
|
u32 get_BAR5(Address address)
|
||||||
{
|
{
|
||||||
return PCI::Access::the().get_BAR5(address);
|
return PCI::Access::the().get_BAR5(address);
|
||||||
}
|
}
|
||||||
u8 get_revision_id(Address address)
|
u8 get_revision_id(Address address)
|
||||||
{
|
{
|
||||||
return PCI::Access::the().get_revision_id(address);
|
return PCI::Access::the().get_revision_id(address);
|
||||||
}
|
}
|
||||||
u8 get_subclass(Address address)
|
u8 get_subclass(Address address)
|
||||||
{
|
{
|
||||||
return PCI::Access::the().get_subclass(address);
|
return PCI::Access::the().get_subclass(address);
|
||||||
}
|
}
|
||||||
u8 get_class(Address address)
|
u8 get_class(Address address)
|
||||||
{
|
{
|
||||||
return PCI::Access::the().get_class(address);
|
return PCI::Access::the().get_class(address);
|
||||||
}
|
}
|
||||||
u16 get_subsystem_id(Address address)
|
u16 get_subsystem_id(Address address)
|
||||||
{
|
{
|
||||||
return PCI::Access::the().get_subsystem_id(address);
|
return PCI::Access::the().get_subsystem_id(address);
|
||||||
}
|
}
|
||||||
u16 get_subsystem_vendor_id(Address address)
|
u16 get_subsystem_vendor_id(Address address)
|
||||||
{
|
{
|
||||||
return PCI::Access::the().get_subsystem_vendor_id(address);
|
return PCI::Access::the().get_subsystem_vendor_id(address);
|
||||||
}
|
}
|
||||||
void enable_bus_mastering(Address address)
|
void enable_bus_mastering(Address address)
|
||||||
{
|
{
|
||||||
PCI::Access::the().enable_bus_mastering(address);
|
PCI::Access::the().enable_bus_mastering(address);
|
||||||
}
|
}
|
||||||
void disable_bus_mastering(Address address)
|
void disable_bus_mastering(Address address)
|
||||||
{
|
{
|
||||||
PCI::Access::the().disable_bus_mastering(address);
|
PCI::Access::the().disable_bus_mastering(address);
|
||||||
}
|
}
|
||||||
size_t get_BAR_Space_Size(Address address, u8 bar_number)
|
size_t get_BAR_Space_Size(Address address, u8 bar_number)
|
||||||
{
|
{
|
||||||
return PCI::Access::the().get_BAR_Space_Size(address, bar_number);
|
return PCI::Access::the().get_BAR_Space_Size(address, bar_number);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,134 +68,134 @@ namespace Kernel {
|
||||||
//#define PCI_DEBUG 1
|
//#define PCI_DEBUG 1
|
||||||
|
|
||||||
namespace PCI {
|
namespace PCI {
|
||||||
struct ID {
|
struct ID {
|
||||||
u16 vendor_id { 0 };
|
u16 vendor_id { 0 };
|
||||||
u16 device_id { 0 };
|
u16 device_id { 0 };
|
||||||
|
|
||||||
bool is_null() const { return !vendor_id && !device_id; }
|
bool is_null() const { return !vendor_id && !device_id; }
|
||||||
|
|
||||||
bool operator==(const ID& other) const
|
bool operator==(const ID& other) const
|
||||||
{
|
{
|
||||||
return vendor_id == other.vendor_id && device_id == other.device_id;
|
return vendor_id == other.vendor_id && device_id == other.device_id;
|
||||||
}
|
}
|
||||||
bool operator!=(const ID& other) const
|
bool operator!=(const ID& other) const
|
||||||
{
|
{
|
||||||
return vendor_id != other.vendor_id || device_id != other.device_id;
|
return vendor_id != other.vendor_id || device_id != other.device_id;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Address {
|
struct Address {
|
||||||
public:
|
public:
|
||||||
Address() {}
|
Address() {}
|
||||||
Address(u16 seg)
|
Address(u16 seg)
|
||||||
: m_seg(seg)
|
: m_seg(seg)
|
||||||
, m_bus(0)
|
, m_bus(0)
|
||||||
, m_slot(0)
|
, m_slot(0)
|
||||||
, m_function(0)
|
, m_function(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
Address(u16 seg, u8 bus, u8 slot, u8 function)
|
Address(u16 seg, u8 bus, u8 slot, u8 function)
|
||||||
: m_seg(seg)
|
: m_seg(seg)
|
||||||
, m_bus(bus)
|
, m_bus(bus)
|
||||||
, m_slot(slot)
|
, m_slot(slot)
|
||||||
, m_function(function)
|
, m_function(function)
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
Address(const Address& address)
|
|
||||||
: m_seg(address.seg())
|
|
||||||
, m_bus(address.bus())
|
|
||||||
, m_slot(address.slot())
|
|
||||||
, m_function(address.function())
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
bool is_null() const { return !m_bus && !m_slot && !m_function; }
|
|
||||||
operator bool() const { return !is_null(); }
|
|
||||||
|
|
||||||
u16 seg() const { return m_seg; }
|
|
||||||
u8 bus() const { return m_bus; }
|
|
||||||
u8 slot() const { return m_slot; }
|
|
||||||
u8 function() const { return m_function; }
|
|
||||||
|
|
||||||
u32 io_address_for_field(u8 field) const
|
|
||||||
{
|
|
||||||
return 0x80000000u | (m_bus << 16u) | (m_slot << 11u) | (m_function << 8u) | (field & 0xfc);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
u32 m_seg { 0 };
|
|
||||||
u8 m_bus { 0 };
|
|
||||||
u8 m_slot { 0 };
|
|
||||||
u8 m_function { 0 };
|
|
||||||
};
|
|
||||||
|
|
||||||
inline const LogStream& operator<<(const LogStream& stream, const Address value)
|
|
||||||
{
|
{
|
||||||
return stream << "PCI [" << String::format("%w", value.seg()) << ":" << String::format("%b", value.bus()) << ":" << String::format("%b", value.slot()) << "." << String::format("%b", value.function()) << "]";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ChangeableAddress : public Address {
|
Address(const Address& address)
|
||||||
ChangeableAddress()
|
: m_seg(address.seg())
|
||||||
: Address(0)
|
, m_bus(address.bus())
|
||||||
{
|
, m_slot(address.slot())
|
||||||
}
|
, m_function(address.function())
|
||||||
explicit ChangeableAddress(u16 seg)
|
{
|
||||||
: Address(seg)
|
}
|
||||||
{
|
|
||||||
}
|
|
||||||
ChangeableAddress(u16 seg, u8 bus, u8 slot, u8 function)
|
|
||||||
: Address(seg, bus, slot, function)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
void set_seg(u16 seg) { m_seg = seg; }
|
|
||||||
void set_bus(u8 bus) { m_bus = bus; }
|
|
||||||
void set_slot(u8 slot) { m_slot = slot; }
|
|
||||||
void set_function(u8 function) { m_function = function; }
|
|
||||||
bool operator==(const Address& address)
|
|
||||||
{
|
|
||||||
if (m_seg == address.seg() && m_bus == address.bus() && m_slot == address.slot() && m_function == address.function())
|
|
||||||
return true;
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
const ChangeableAddress& operator=(const Address& address)
|
|
||||||
{
|
|
||||||
set_seg(address.seg());
|
|
||||||
set_bus(address.bus());
|
|
||||||
set_slot(address.slot());
|
|
||||||
set_function(address.function());
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
ID get_id(PCI::Address);
|
bool is_null() const { return !m_bus && !m_slot && !m_function; }
|
||||||
void enumerate_all(Function<void(Address, ID)> callback);
|
operator bool() const { return !is_null(); }
|
||||||
void enable_interrupt_line(Address);
|
|
||||||
void disable_interrupt_line(Address);
|
|
||||||
u8 get_interrupt_line(Address);
|
|
||||||
void raw_access(Address, u32, size_t, u32);
|
|
||||||
u32 get_BAR0(Address);
|
|
||||||
u32 get_BAR1(Address);
|
|
||||||
u32 get_BAR2(Address);
|
|
||||||
u32 get_BAR3(Address);
|
|
||||||
u32 get_BAR4(Address);
|
|
||||||
u32 get_BAR5(Address);
|
|
||||||
u8 get_revision_id(Address);
|
|
||||||
u8 get_subclass(Address);
|
|
||||||
u8 get_class(Address);
|
|
||||||
u16 get_subsystem_id(Address);
|
|
||||||
u16 get_subsystem_vendor_id(Address);
|
|
||||||
size_t get_BAR_Space_Size(Address, u8);
|
|
||||||
void enable_bus_mastering(Address);
|
|
||||||
void disable_bus_mastering(Address);
|
|
||||||
|
|
||||||
class Initializer;
|
u16 seg() const { return m_seg; }
|
||||||
class Access;
|
u8 bus() const { return m_bus; }
|
||||||
class MMIOAccess;
|
u8 slot() const { return m_slot; }
|
||||||
class IOAccess;
|
u8 function() const { return m_function; }
|
||||||
class MMIOSegment;
|
|
||||||
class Device;
|
u32 io_address_for_field(u8 field) const
|
||||||
|
{
|
||||||
|
return 0x80000000u | (m_bus << 16u) | (m_slot << 11u) | (m_function << 8u) | (field & 0xfc);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
u32 m_seg { 0 };
|
||||||
|
u8 m_bus { 0 };
|
||||||
|
u8 m_slot { 0 };
|
||||||
|
u8 m_function { 0 };
|
||||||
|
};
|
||||||
|
|
||||||
|
inline const LogStream& operator<<(const LogStream& stream, const Address value)
|
||||||
|
{
|
||||||
|
return stream << "PCI [" << String::format("%w", value.seg()) << ":" << String::format("%b", value.bus()) << ":" << String::format("%b", value.slot()) << "." << String::format("%b", value.function()) << "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ChangeableAddress : public Address {
|
||||||
|
ChangeableAddress()
|
||||||
|
: Address(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
explicit ChangeableAddress(u16 seg)
|
||||||
|
: Address(seg)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
ChangeableAddress(u16 seg, u8 bus, u8 slot, u8 function)
|
||||||
|
: Address(seg, bus, slot, function)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
void set_seg(u16 seg) { m_seg = seg; }
|
||||||
|
void set_bus(u8 bus) { m_bus = bus; }
|
||||||
|
void set_slot(u8 slot) { m_slot = slot; }
|
||||||
|
void set_function(u8 function) { m_function = function; }
|
||||||
|
bool operator==(const Address& address)
|
||||||
|
{
|
||||||
|
if (m_seg == address.seg() && m_bus == address.bus() && m_slot == address.slot() && m_function == address.function())
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const ChangeableAddress& operator=(const Address& address)
|
||||||
|
{
|
||||||
|
set_seg(address.seg());
|
||||||
|
set_bus(address.bus());
|
||||||
|
set_slot(address.slot());
|
||||||
|
set_function(address.function());
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ID get_id(PCI::Address);
|
||||||
|
void enumerate_all(Function<void(Address, ID)> callback);
|
||||||
|
void enable_interrupt_line(Address);
|
||||||
|
void disable_interrupt_line(Address);
|
||||||
|
u8 get_interrupt_line(Address);
|
||||||
|
void raw_access(Address, u32, size_t, u32);
|
||||||
|
u32 get_BAR0(Address);
|
||||||
|
u32 get_BAR1(Address);
|
||||||
|
u32 get_BAR2(Address);
|
||||||
|
u32 get_BAR3(Address);
|
||||||
|
u32 get_BAR4(Address);
|
||||||
|
u32 get_BAR5(Address);
|
||||||
|
u8 get_revision_id(Address);
|
||||||
|
u8 get_subclass(Address);
|
||||||
|
u8 get_class(Address);
|
||||||
|
u16 get_subsystem_id(Address);
|
||||||
|
u16 get_subsystem_vendor_id(Address);
|
||||||
|
size_t get_BAR_Space_Size(Address, u8);
|
||||||
|
void enable_bus_mastering(Address);
|
||||||
|
void disable_bus_mastering(Address);
|
||||||
|
|
||||||
|
class Initializer;
|
||||||
|
class Access;
|
||||||
|
class MMIOAccess;
|
||||||
|
class IOAccess;
|
||||||
|
class MMIOSegment;
|
||||||
|
class Device;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <AK/JsonArraySerializer.h>
|
#include <AK/JsonArraySerializer.h>
|
||||||
#include <AK/JsonObjectSerializer.h>
|
|
||||||
#include <AK/JsonObject.h>
|
#include <AK/JsonObject.h>
|
||||||
|
#include <AK/JsonObjectSerializer.h>
|
||||||
#include <Kernel/KBufferBuilder.h>
|
#include <Kernel/KBufferBuilder.h>
|
||||||
#include <Kernel/PerformanceEventBuffer.h>
|
#include <Kernel/PerformanceEventBuffer.h>
|
||||||
|
|
||||||
|
|
|
@ -65,61 +65,61 @@ asm(
|
||||||
|
|
||||||
namespace Syscall {
|
namespace Syscall {
|
||||||
|
|
||||||
static int handle(RegisterState&, u32 function, u32 arg1, u32 arg2, u32 arg3);
|
static int handle(RegisterState&, u32 function, u32 arg1, u32 arg2, u32 arg3);
|
||||||
|
|
||||||
void initialize()
|
void initialize()
|
||||||
{
|
{
|
||||||
register_user_callable_interrupt_handler(0x82, syscall_asm_entry);
|
register_user_callable_interrupt_handler(0x82, syscall_asm_entry);
|
||||||
klog() << "Syscall: int 0x82 handler installed";
|
klog() << "Syscall: int 0x82 handler installed";
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma GCC diagnostic ignored "-Wcast-function-type"
|
#pragma GCC diagnostic ignored "-Wcast-function-type"
|
||||||
typedef int (Process::*Handler)(u32, u32, u32);
|
typedef int (Process::*Handler)(u32, u32, u32);
|
||||||
#define __ENUMERATE_REMOVED_SYSCALL(x) nullptr,
|
#define __ENUMERATE_REMOVED_SYSCALL(x) nullptr,
|
||||||
#define __ENUMERATE_SYSCALL(x) reinterpret_cast<Handler>(&Process::sys$##x),
|
#define __ENUMERATE_SYSCALL(x) reinterpret_cast<Handler>(&Process::sys$##x),
|
||||||
static Handler s_syscall_table[] = {
|
static Handler s_syscall_table[] = {
|
||||||
ENUMERATE_SYSCALLS
|
ENUMERATE_SYSCALLS
|
||||||
};
|
};
|
||||||
#undef __ENUMERATE_SYSCALL
|
#undef __ENUMERATE_SYSCALL
|
||||||
#undef __ENUMERATE_REMOVED_SYSCALL
|
#undef __ENUMERATE_REMOVED_SYSCALL
|
||||||
|
|
||||||
int handle(RegisterState& regs, u32 function, u32 arg1, u32 arg2, u32 arg3)
|
int handle(RegisterState& regs, u32 function, u32 arg1, u32 arg2, u32 arg3)
|
||||||
{
|
{
|
||||||
ASSERT_INTERRUPTS_ENABLED();
|
ASSERT_INTERRUPTS_ENABLED();
|
||||||
auto& process = *Process::current;
|
auto& process = *Process::current;
|
||||||
Thread::current->did_syscall();
|
Thread::current->did_syscall();
|
||||||
|
|
||||||
if (function == SC_exit || function == SC_exit_thread) {
|
if (function == SC_exit || function == SC_exit_thread) {
|
||||||
// These syscalls need special handling since they never return to the caller.
|
// These syscalls need special handling since they never return to the caller.
|
||||||
cli();
|
cli();
|
||||||
if (auto* tracer = process.tracer())
|
if (auto* tracer = process.tracer())
|
||||||
tracer->did_syscall(function, arg1, arg2, arg3, 0);
|
tracer->did_syscall(function, arg1, arg2, arg3, 0);
|
||||||
if (function == SC_exit)
|
if (function == SC_exit)
|
||||||
process.sys$exit((int)arg1);
|
process.sys$exit((int)arg1);
|
||||||
else
|
else
|
||||||
process.sys$exit_thread((void*)arg1);
|
process.sys$exit_thread((void*)arg1);
|
||||||
ASSERT_NOT_REACHED();
|
ASSERT_NOT_REACHED();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
|
||||||
|
|
||||||
if (function == SC_fork)
|
|
||||||
return process.sys$fork(regs);
|
|
||||||
|
|
||||||
if (function == SC_sigreturn)
|
|
||||||
return process.sys$sigreturn(regs);
|
|
||||||
|
|
||||||
if (function >= Function::__Count) {
|
|
||||||
dbg() << process << ": Unknown syscall %u requested (" << arg1 << ", " << arg2 << ", " << arg3 << ")";
|
|
||||||
return -ENOSYS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (s_syscall_table[function] == nullptr) {
|
|
||||||
dbg() << process << ": Null syscall " << function << " requested: \"" << to_string((Function)function) << "\", you probably need to rebuild this program.";
|
|
||||||
return -ENOSYS;
|
|
||||||
}
|
|
||||||
return (process.*(s_syscall_table[function]))(arg1, arg2, arg3);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (function == SC_fork)
|
||||||
|
return process.sys$fork(regs);
|
||||||
|
|
||||||
|
if (function == SC_sigreturn)
|
||||||
|
return process.sys$sigreturn(regs);
|
||||||
|
|
||||||
|
if (function >= Function::__Count) {
|
||||||
|
dbg() << process << ": Unknown syscall %u requested (" << arg1 << ", " << arg2 << ", " << arg3 << ")";
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_syscall_table[function] == nullptr) {
|
||||||
|
dbg() << process << ": Null syscall " << function << " requested: \"" << to_string((Function)function) << "\", you probably need to rebuild this program.";
|
||||||
|
return -ENOSYS;
|
||||||
|
}
|
||||||
|
return (process.*(s_syscall_table[function]))(arg1, arg2, arg3);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void syscall_handler(RegisterState& regs)
|
void syscall_handler(RegisterState& regs)
|
||||||
|
|
456
Kernel/Syscall.h
456
Kernel/Syscall.h
|
@ -184,20 +184,20 @@ namespace Kernel {
|
||||||
|
|
||||||
namespace Syscall {
|
namespace Syscall {
|
||||||
|
|
||||||
enum Function {
|
enum Function {
|
||||||
#undef __ENUMERATE_SYSCALL
|
#undef __ENUMERATE_SYSCALL
|
||||||
#undef __ENUMERATE_REMOVED_SYSCALL
|
#undef __ENUMERATE_REMOVED_SYSCALL
|
||||||
#define __ENUMERATE_REMOVED_SYSCALL(x) SC_##x,
|
#define __ENUMERATE_REMOVED_SYSCALL(x) SC_##x,
|
||||||
#define __ENUMERATE_SYSCALL(x) SC_##x,
|
#define __ENUMERATE_SYSCALL(x) SC_##x,
|
||||||
ENUMERATE_SYSCALLS
|
ENUMERATE_SYSCALLS
|
||||||
#undef __ENUMERATE_SYSCALL
|
#undef __ENUMERATE_SYSCALL
|
||||||
#undef __ENUMERATE_REMOVED_SYSCALL
|
#undef __ENUMERATE_REMOVED_SYSCALL
|
||||||
__Count
|
__Count
|
||||||
};
|
};
|
||||||
|
|
||||||
inline constexpr const char* to_string(Function function)
|
inline constexpr const char* to_string(Function function)
|
||||||
{
|
{
|
||||||
switch (function) {
|
switch (function) {
|
||||||
#undef __ENUMERATE_SYSCALL
|
#undef __ENUMERATE_SYSCALL
|
||||||
#undef __ENUMERATE_REMOVED_SYSCALL
|
#undef __ENUMERATE_REMOVED_SYSCALL
|
||||||
#define __ENUMERATE_REMOVED_SYSCALL(x) \
|
#define __ENUMERATE_REMOVED_SYSCALL(x) \
|
||||||
|
@ -206,267 +206,267 @@ namespace Syscall {
|
||||||
#define __ENUMERATE_SYSCALL(x) \
|
#define __ENUMERATE_SYSCALL(x) \
|
||||||
case SC_##x: \
|
case SC_##x: \
|
||||||
return #x;
|
return #x;
|
||||||
ENUMERATE_SYSCALLS
|
ENUMERATE_SYSCALLS
|
||||||
#undef __ENUMERATE_SYSCALL
|
#undef __ENUMERATE_SYSCALL
|
||||||
#undef __ENUMERATE_REMOVED_SYSCALL
|
#undef __ENUMERATE_REMOVED_SYSCALL
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
return "Unknown";
|
|
||||||
}
|
}
|
||||||
|
return "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef __serenity__
|
#ifdef __serenity__
|
||||||
struct StringArgument {
|
struct StringArgument {
|
||||||
const char* characters { nullptr };
|
const char* characters { nullptr };
|
||||||
size_t length { 0 };
|
size_t length { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename DataType, typename SizeType>
|
template<typename DataType, typename SizeType>
|
||||||
struct MutableBufferArgument {
|
struct MutableBufferArgument {
|
||||||
DataType* data { nullptr };
|
DataType* data { nullptr };
|
||||||
SizeType size { 0 };
|
SizeType size { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename DataType, typename SizeType>
|
template<typename DataType, typename SizeType>
|
||||||
struct ImmutableBufferArgument {
|
struct ImmutableBufferArgument {
|
||||||
const DataType* data { nullptr };
|
const DataType* data { nullptr };
|
||||||
SizeType size { 0 };
|
SizeType size { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StringListArgument {
|
struct StringListArgument {
|
||||||
StringArgument* strings { nullptr };
|
StringArgument* strings { nullptr };
|
||||||
size_t length { 0 };
|
size_t length { 0 };
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SC_mmap_params {
|
struct SC_mmap_params {
|
||||||
uint32_t addr;
|
uint32_t addr;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
uint32_t alignment;
|
uint32_t alignment;
|
||||||
int32_t prot;
|
int32_t prot;
|
||||||
int32_t flags;
|
int32_t flags;
|
||||||
int32_t fd;
|
int32_t fd;
|
||||||
int32_t offset; // FIXME: 64-bit off_t?
|
int32_t offset; // FIXME: 64-bit off_t?
|
||||||
StringArgument name;
|
StringArgument name;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SC_open_params {
|
struct SC_open_params {
|
||||||
int dirfd;
|
int dirfd;
|
||||||
StringArgument path;
|
StringArgument path;
|
||||||
int options;
|
int options;
|
||||||
u16 mode;
|
u16 mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SC_select_params {
|
struct SC_select_params {
|
||||||
int nfds;
|
int nfds;
|
||||||
fd_set* readfds;
|
fd_set* readfds;
|
||||||
fd_set* writefds;
|
fd_set* writefds;
|
||||||
fd_set* exceptfds;
|
fd_set* exceptfds;
|
||||||
struct timeval* timeout;
|
struct timeval* timeout;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SC_clock_nanosleep_params {
|
struct SC_clock_nanosleep_params {
|
||||||
int clock_id;
|
int clock_id;
|
||||||
int flags;
|
int flags;
|
||||||
const struct timespec* requested_sleep;
|
const struct timespec* requested_sleep;
|
||||||
struct timespec* remaining_sleep;
|
struct timespec* remaining_sleep;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SC_sendto_params {
|
struct SC_sendto_params {
|
||||||
int sockfd;
|
int sockfd;
|
||||||
ImmutableBufferArgument<void, size_t> data;
|
ImmutableBufferArgument<void, size_t> data;
|
||||||
int flags;
|
int flags;
|
||||||
const sockaddr* addr;
|
const sockaddr* addr;
|
||||||
socklen_t addr_length;
|
socklen_t addr_length;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SC_recvfrom_params {
|
struct SC_recvfrom_params {
|
||||||
int sockfd;
|
int sockfd;
|
||||||
MutableBufferArgument<void, size_t> buffer;
|
MutableBufferArgument<void, size_t> buffer;
|
||||||
int flags;
|
int flags;
|
||||||
sockaddr* addr;
|
sockaddr* addr;
|
||||||
socklen_t* addr_length;
|
socklen_t* addr_length;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SC_getsockopt_params {
|
struct SC_getsockopt_params {
|
||||||
int sockfd;
|
int sockfd;
|
||||||
int level;
|
int level;
|
||||||
int option;
|
int option;
|
||||||
void* value;
|
void* value;
|
||||||
socklen_t* value_size;
|
socklen_t* value_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SC_setsockopt_params {
|
struct SC_setsockopt_params {
|
||||||
int sockfd;
|
int sockfd;
|
||||||
int level;
|
int level;
|
||||||
int option;
|
int option;
|
||||||
const void* value;
|
const void* value;
|
||||||
socklen_t value_size;
|
socklen_t value_size;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SC_getsockname_params {
|
struct SC_getsockname_params {
|
||||||
int sockfd;
|
int sockfd;
|
||||||
sockaddr* addr;
|
sockaddr* addr;
|
||||||
socklen_t* addrlen;
|
socklen_t* addrlen;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SC_getpeername_params {
|
struct SC_getpeername_params {
|
||||||
int sockfd;
|
int sockfd;
|
||||||
sockaddr* addr;
|
sockaddr* addr;
|
||||||
socklen_t* addrlen;
|
socklen_t* addrlen;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SC_futex_params {
|
struct SC_futex_params {
|
||||||
i32* userspace_address;
|
i32* userspace_address;
|
||||||
int futex_op;
|
int futex_op;
|
||||||
i32 val;
|
i32 val;
|
||||||
const timespec* timeout;
|
const timespec* timeout;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SC_setkeymap_params {
|
struct SC_setkeymap_params {
|
||||||
const char* map;
|
const char* map;
|
||||||
const char* shift_map;
|
const char* shift_map;
|
||||||
const char* alt_map;
|
const char* alt_map;
|
||||||
const char* altgr_map;
|
const char* altgr_map;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SC_create_thread_params {
|
struct SC_create_thread_params {
|
||||||
unsigned int m_detach_state = 0; // JOINABLE or DETACHED
|
unsigned int m_detach_state = 0; // JOINABLE or DETACHED
|
||||||
int m_schedule_priority = 30; // THREAD_PRIORITY_NORMAL
|
int m_schedule_priority = 30; // THREAD_PRIORITY_NORMAL
|
||||||
// FIXME: Implment guard pages in create_thread (unreadable pages at "overflow" end of stack)
|
// FIXME: Implment guard pages in create_thread (unreadable pages at "overflow" end of stack)
|
||||||
// "If an implementation rounds up the value of guardsize to a multiple of {PAGESIZE},
|
// "If an implementation rounds up the value of guardsize to a multiple of {PAGESIZE},
|
||||||
// a call to pthread_attr_getguardsize() specifying attr shall store in the guardsize
|
// a call to pthread_attr_getguardsize() specifying attr shall store in the guardsize
|
||||||
// parameter the guard size specified by the previous pthread_attr_setguardsize() function call"
|
// parameter the guard size specified by the previous pthread_attr_setguardsize() function call"
|
||||||
// ... ok, if you say so posix. Guess we get to lie to people about guard page size
|
// ... ok, if you say so posix. Guess we get to lie to people about guard page size
|
||||||
unsigned int m_guard_page_size = 0; // Rounded up to PAGE_SIZE
|
unsigned int m_guard_page_size = 0; // Rounded up to PAGE_SIZE
|
||||||
unsigned int m_reported_guard_page_size = 0; // The lie we tell callers
|
unsigned int m_reported_guard_page_size = 0; // The lie we tell callers
|
||||||
unsigned int m_stack_size = 4 * MB; // Default PTHREAD_STACK_MIN
|
unsigned int m_stack_size = 4 * MB; // Default PTHREAD_STACK_MIN
|
||||||
void* m_stack_location = nullptr; // nullptr means any, o.w. process virtual address
|
void* m_stack_location = nullptr; // nullptr means any, o.w. process virtual address
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SC_realpath_params {
|
struct SC_realpath_params {
|
||||||
StringArgument path;
|
StringArgument path;
|
||||||
MutableBufferArgument<char, size_t> buffer;
|
MutableBufferArgument<char, size_t> buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SC_set_mmap_name_params {
|
struct SC_set_mmap_name_params {
|
||||||
void* addr;
|
void* addr;
|
||||||
size_t size;
|
size_t size;
|
||||||
StringArgument name;
|
StringArgument name;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SC_execve_params {
|
struct SC_execve_params {
|
||||||
StringArgument path;
|
StringArgument path;
|
||||||
StringListArgument arguments;
|
StringListArgument arguments;
|
||||||
StringListArgument environment;
|
StringListArgument environment;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SC_readlink_params {
|
struct SC_readlink_params {
|
||||||
StringArgument path;
|
StringArgument path;
|
||||||
MutableBufferArgument<char, size_t> buffer;
|
MutableBufferArgument<char, size_t> buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SC_link_params {
|
struct SC_link_params {
|
||||||
StringArgument old_path;
|
StringArgument old_path;
|
||||||
StringArgument new_path;
|
StringArgument new_path;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SC_chown_params {
|
struct SC_chown_params {
|
||||||
StringArgument path;
|
StringArgument path;
|
||||||
u32 uid;
|
u32 uid;
|
||||||
u32 gid;
|
u32 gid;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SC_mknod_params {
|
struct SC_mknod_params {
|
||||||
StringArgument path;
|
StringArgument path;
|
||||||
u16 mode;
|
u16 mode;
|
||||||
u32 dev;
|
u32 dev;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SC_symlink_params {
|
struct SC_symlink_params {
|
||||||
StringArgument target;
|
StringArgument target;
|
||||||
StringArgument linkpath;
|
StringArgument linkpath;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SC_rename_params {
|
struct SC_rename_params {
|
||||||
StringArgument old_path;
|
StringArgument old_path;
|
||||||
StringArgument new_path;
|
StringArgument new_path;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SC_mount_params {
|
struct SC_mount_params {
|
||||||
StringArgument source;
|
StringArgument source;
|
||||||
StringArgument target;
|
StringArgument target;
|
||||||
StringArgument fs_type;
|
StringArgument fs_type;
|
||||||
int flags;
|
int flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SC_pledge_params {
|
struct SC_pledge_params {
|
||||||
StringArgument promises;
|
StringArgument promises;
|
||||||
StringArgument execpromises;
|
StringArgument execpromises;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SC_unveil_params {
|
struct SC_unveil_params {
|
||||||
StringArgument path;
|
StringArgument path;
|
||||||
StringArgument permissions;
|
StringArgument permissions;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SC_waitid_params {
|
struct SC_waitid_params {
|
||||||
int idtype;
|
int idtype;
|
||||||
int id;
|
int id;
|
||||||
struct siginfo* infop;
|
struct siginfo* infop;
|
||||||
int options;
|
int options;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SC_stat_params {
|
struct SC_stat_params {
|
||||||
StringArgument path;
|
StringArgument path;
|
||||||
struct stat* statbuf;
|
struct stat* statbuf;
|
||||||
bool follow_symlinks;
|
bool follow_symlinks;
|
||||||
};
|
};
|
||||||
|
|
||||||
void initialize();
|
void initialize();
|
||||||
int sync();
|
int sync();
|
||||||
|
|
||||||
inline u32 invoke(Function function)
|
inline u32 invoke(Function function)
|
||||||
{
|
{
|
||||||
u32 result;
|
u32 result;
|
||||||
asm volatile("int $0x82"
|
asm volatile("int $0x82"
|
||||||
: "=a"(result)
|
: "=a"(result)
|
||||||
: "a"(function)
|
: "a"(function)
|
||||||
: "memory");
|
: "memory");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T1>
|
template<typename T1>
|
||||||
inline u32 invoke(Function function, T1 arg1)
|
inline u32 invoke(Function function, T1 arg1)
|
||||||
{
|
{
|
||||||
u32 result;
|
u32 result;
|
||||||
asm volatile("int $0x82"
|
asm volatile("int $0x82"
|
||||||
: "=a"(result)
|
: "=a"(result)
|
||||||
: "a"(function), "d"((u32)arg1)
|
: "a"(function), "d"((u32)arg1)
|
||||||
: "memory");
|
: "memory");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T1, typename T2>
|
template<typename T1, typename T2>
|
||||||
inline u32 invoke(Function function, T1 arg1, T2 arg2)
|
inline u32 invoke(Function function, T1 arg1, T2 arg2)
|
||||||
{
|
{
|
||||||
u32 result;
|
u32 result;
|
||||||
asm volatile("int $0x82"
|
asm volatile("int $0x82"
|
||||||
: "=a"(result)
|
: "=a"(result)
|
||||||
: "a"(function), "d"((u32)arg1), "c"((u32)arg2)
|
: "a"(function), "d"((u32)arg1), "c"((u32)arg2)
|
||||||
: "memory");
|
: "memory");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T1, typename T2, typename T3>
|
template<typename T1, typename T2, typename T3>
|
||||||
inline u32 invoke(Function function, T1 arg1, T2 arg2, T3 arg3)
|
inline u32 invoke(Function function, T1 arg1, T2 arg2, T3 arg3)
|
||||||
{
|
{
|
||||||
u32 result;
|
u32 result;
|
||||||
asm volatile("int $0x82"
|
asm volatile("int $0x82"
|
||||||
: "=a"(result)
|
: "=a"(result)
|
||||||
: "a"(function), "d"((u32)arg1), "c"((u32)arg2), "b"((u32)arg3)
|
: "a"(function), "d"((u32)arg1), "c"((u32)arg2), "b"((u32)arg3)
|
||||||
: "memory");
|
: "memory");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,9 +24,9 @@
|
||||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <Kernel/Heap/kmalloc.h>
|
||||||
#include <Kernel/VM/MemoryManager.h>
|
#include <Kernel/VM/MemoryManager.h>
|
||||||
#include <Kernel/VM/PhysicalPage.h>
|
#include <Kernel/VM/PhysicalPage.h>
|
||||||
#include <Kernel/Heap/kmalloc.h>
|
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue