From f85dbe582f13dc9f415f0e5e4a883f9173c60195 Mon Sep 17 00:00:00 2001 From: Undefine Date: Fri, 6 Nov 2026 18:54:51 +0100 Subject: [PATCH] Kernel: Add read_generic_address This will be needed to properly implement ACPI shutdown. It's also missing PCI configuration space support unlike write_generic_address, because it would require messing with the PCI subsystem and it's not necessary for now. --- Kernel/Firmware/ACPI/GenericAddress.cpp | 54 +++++++++++++++++++++++++ Kernel/Firmware/ACPI/GenericAddress.h | 1 + 2 files changed, 55 insertions(+) diff --git a/Kernel/Firmware/ACPI/GenericAddress.cpp b/Kernel/Firmware/ACPI/GenericAddress.cpp index b0e65e51ac1..4c48dbb130c 100644 --- a/Kernel/Firmware/ACPI/GenericAddress.cpp +++ b/Kernel/Firmware/ACPI/GenericAddress.cpp @@ -44,6 +44,60 @@ static ErrorOr get_bit_width(::ACPI::Structures::GenericAddressStructure con return AK::min(bit_width, structure.address_space == ::ACPI::GenericAddressStructure::AddressSpace::SystemIO ? 32 : 64); } +ErrorOr read_generic_address(::ACPI::Structures::GenericAddressStructure const& structure) +{ + auto bit_width = TRY(get_bit_width(structure)); + + switch (structure.address_space) { + case ::ACPI::GenericAddressStructure::AddressSpace::SystemIO: { +#if ARCH(X86_64) + IOAddress address(structure.address); + dbgln_if(ACPI_DEBUG, "ACPI: Reading from {}", address); + + switch (bit_width) { + case 8: + return address.in(); + case 16: + return address.in(); + case 32: + return address.in(); + default: + dbgln("ACPI: Tried to read an unsupported bit width from an IO port"); + return EINVAL; + } +#else + dbgln("ACPI: Tried to access SystemIO on a non x86 architecture"); + return EINVAL; +#endif + } + + case ::ACPI::GenericAddressStructure::AddressSpace::SystemMemory: { + dbgln_if(ACPI_DEBUG, "ACPI: Reading from {}", PhysicalAddress(structure.address)); + + switch (bit_width) { + case 8: + return *TRY(Memory::map_typed(PhysicalAddress(structure.address))); + case 16: + return *TRY(Memory::map_typed(PhysicalAddress(structure.address))); + case 32: + return *TRY(Memory::map_typed(PhysicalAddress(structure.address))); + case 64: + return *TRY(Memory::map_typed(PhysicalAddress(structure.address))); + + default: + dbgln("ACPI: Tried to read an unsupported bit width from SystemMemory"); + return EINVAL; + } + } + + default: + dbgln("ACPI: Tried to access an unsupported address space"); + return EINVAL; + } + + VERIFY_NOT_REACHED(); +} + ErrorOr write_generic_address(::ACPI::Structures::GenericAddressStructure const& structure, u64 value) { auto bit_width = TRY(get_bit_width(structure)); diff --git a/Kernel/Firmware/ACPI/GenericAddress.h b/Kernel/Firmware/ACPI/GenericAddress.h index 3af8fb76227..68b79f425a2 100644 --- a/Kernel/Firmware/ACPI/GenericAddress.h +++ b/Kernel/Firmware/ACPI/GenericAddress.h @@ -11,6 +11,7 @@ namespace Kernel::ACPI { +ErrorOr read_generic_address(::ACPI::Structures::GenericAddressStructure const& structure); ErrorOr write_generic_address(::ACPI::Structures::GenericAddressStructure const& structure, u64 value); }