From f48e71e070217cdba662dcc588e903f085c84777 Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Tue, 31 Jan 2017 20:46:18 +0100 Subject: [PATCH] acpica: use platform_info for rsdt/xsdt lookup Issue #2242 --- repos/libports/lib/mk/acpica.mk | 2 +- repos/libports/src/lib/acpica/iomem.cc | 116 ++++++++++++++++++++- repos/libports/src/lib/acpica/scan_root.cc | 105 ------------------- 3 files changed, 115 insertions(+), 108 deletions(-) delete mode 100644 repos/libports/src/lib/acpica/scan_root.cc diff --git a/repos/libports/lib/mk/acpica.mk b/repos/libports/lib/mk/acpica.mk index d47e2c2d3f..dc62769857 100644 --- a/repos/libports/lib/mk/acpica.mk +++ b/repos/libports/lib/mk/acpica.mk @@ -15,7 +15,7 @@ SRC_C += $(addprefix resources/, $(notdir $(wildcard $(ACPICA_COMP)/resources/*. SRC_C += $(addprefix tables/, $(notdir $(wildcard $(ACPICA_COMP)/tables/*.c))) SRC_C += $(addprefix utilities/, $(notdir $(wildcard $(ACPICA_COMP)/utilities/*.c))) -SRC_CC += osl.cc iomem.cc pci.cc scan_root.cc env.cc +SRC_CC += osl.cc iomem.cc pci.cc env.cc include $(REP_DIR)/lib/import/import-acpica.mk diff --git a/repos/libports/src/lib/acpica/iomem.cc b/repos/libports/src/lib/acpica/iomem.cc index c740bcac52..45de9fe9b4 100644 --- a/repos/libports/src/lib/acpica/iomem.cc +++ b/repos/libports/src/lib/acpica/iomem.cc @@ -1,5 +1,6 @@ /* - * \brief I/O memory backend for ACPICA library + * \brief I/O memory backend for ACPICA library and lookup code + * for initial ACPI RSDP pointer * \author Alexander Boettcher * \date 2016-11-14 */ @@ -11,6 +12,8 @@ * under the terms of the GNU Affero General Public License version 3. */ +#include +#include #include #include @@ -32,7 +35,84 @@ extern "C" { return retval; \ } -namespace Acpica { class Io_mem; }; +namespace Acpica { + class Io_mem; + class Rsdp; +}; + + +class Acpica::Rsdp +{ + private: + + /* BIOS range to scan for RSDP */ + enum { BIOS_BASE = 0xe0000, BIOS_SIZE = 0x20000 }; + + /** + * Search for RSDP pointer signature in area + */ + Genode::uint8_t *_search_rsdp(Genode::uint8_t *area, + Genode::size_t const area_size) + { + for (Genode::addr_t addr = 0; area && addr < area_size; addr += 16) + /* XXX checksum table */ + if (!Genode::memcmp(area + addr, "RSD PTR ", 8)) + return area + addr; + + return nullptr; + } + + /** + * Return 'Root System Descriptor Pointer' (ACPI spec 5.2.5.1) + */ + Genode::uint64_t _rsdp(Genode::Env &env) + { + Genode::uint8_t * local = 0; + + /* try BIOS area */ + { + Genode::Attached_io_mem_dataspace io_mem(env, BIOS_BASE, BIOS_SIZE); + local = _search_rsdp(io_mem.local_addr(), BIOS_SIZE); + if (local) + return BIOS_BASE + (local - io_mem.local_addr()); + } + + /* search EBDA (BIOS addr + 0x40e) */ + try { + unsigned short base = 0; + { + Genode::Attached_io_mem_dataspace io_mem(env, 0, 0x1000); + local = io_mem.local_addr(); + if (local) + base = (*reinterpret_cast(local + 0x40e)) << 4; + } + + if (!base) + return 0; + + Genode::Attached_io_mem_dataspace io_mem(env, base, 1024); + local = _search_rsdp(io_mem.local_addr(), 1024); + + if (local) + return base + (local - io_mem.local_addr()); + } catch (...) { + Genode::warning("failed to scan EBDA for RSDP root"); + } + + return 0; + } + + public: + + Rsdp() { } + + Genode::addr_t phys_rsdp(Genode::Env &env) + { + Genode::uint64_t phys_rsdp = _rsdp(env); + return phys_rsdp; + } +}; + class Acpica::Io_mem { @@ -231,9 +311,38 @@ class Acpica::Io_mem Acpica::Io_mem Acpica::Io_mem::_ios[32]; +static ACPI_TABLE_RSDP faked_rsdp; +enum { FAKED_PHYS_RSDP_ADDR = 1 }; + +ACPI_PHYSICAL_ADDRESS AcpiOsGetRootPointer (void) +{ + Genode::Env &env = Acpica::env(); + + /* try platform_info ROM provided by core */ + try { + Genode::Attached_rom_dataspace info(env, "platform_info"); + Genode::Xml_node xml(info.local_addr(), info.size()); + Genode::Xml_node acpi_node = xml.sub_node("acpi"); + + faked_rsdp.Revision = acpi_node.attribute_value("revision", 0U); + faked_rsdp.RsdtPhysicalAddress = acpi_node.attribute_value("rsdt", 0UL); + faked_rsdp.XsdtPhysicalAddress = acpi_node.attribute_value("xsdt", 0UL); + + if (faked_rsdp.XsdtPhysicalAddress || faked_rsdp.RsdtPhysicalAddress) + return FAKED_PHYS_RSDP_ADDR; + } catch (...) { } + + /* legacy way - search and grep for the pointer */ + Acpica::Rsdp acpi_table; + ACPI_PHYSICAL_ADDRESS rsdp = acpi_table.phys_rsdp(env); + return rsdp; +} void * AcpiOsMapMemory (ACPI_PHYSICAL_ADDRESS phys, ACPI_SIZE size) { + if (phys == FAKED_PHYS_RSDP_ADDR) + return &faked_rsdp; + Genode::addr_t virt = Acpica::Io_mem::apply_u([&] (Acpica::Io_mem &io_mem) { if (io_mem.unused() || io_mem.stale()) return 0UL; @@ -265,6 +374,9 @@ void * AcpiOsMapMemory (ACPI_PHYSICAL_ADDRESS phys, ACPI_SIZE size) void AcpiOsUnmapMemory (void * ptr, ACPI_SIZE size) { + if (ptr == &faked_rsdp) + return; + Genode::uint8_t const * virt = reinterpret_cast(ptr); if (Acpica::Io_mem::apply_u([&] (Acpica::Io_mem &io_mem) { diff --git a/repos/libports/src/lib/acpica/scan_root.cc b/repos/libports/src/lib/acpica/scan_root.cc deleted file mode 100644 index 2331cd0d68..0000000000 --- a/repos/libports/src/lib/acpica/scan_root.cc +++ /dev/null @@ -1,105 +0,0 @@ -/* - * \brief Lookup code for initial ACPI RSDP pointer - * \author Alexander Boettcher - * \date 2016-11-14 - */ - -/* - * Copyright (C) 2016-2017 Genode Labs GmbH - * - * This file is part of the Genode OS framework, which is distributed - * under the terms of the GNU Affero General Public License version 3. - */ - -#include -#include - -#include "env.h" - -extern "C" { -#include "acpi.h" -} - -namespace Genode { - class Acpi_table; -} - -class Genode::Acpi_table -{ - private: - - /* BIOS range to scan for RSDP */ - enum { BIOS_BASE = 0xe0000, BIOS_SIZE = 0x20000 }; - - /** - * Search for RSDP pointer signature in area - */ - uint8_t *_search_rsdp(uint8_t *area) - { - for (addr_t addr = 0; area && addr < BIOS_SIZE; addr += 16) - /* XXX checksum table */ - if (!memcmp(area + addr, "RSD PTR ", 8)) - return area + addr; - - return nullptr; - } - - /** - * Return 'Root System Descriptor Pointer' (ACPI spec 5.2.5.1) - */ - uint64_t _rsdp() - { - uint8_t * local = 0; - - Genode::Env &env = Acpica::env(); - - /* try BIOS area */ - { - Genode::Attached_io_mem_dataspace io_mem(env, BIOS_BASE, BIOS_SIZE); - local = _search_rsdp(io_mem.local_addr()); - if (local) - return BIOS_BASE + (local - io_mem.local_addr()); - } - - /* search EBDA (BIOS addr + 0x40e) */ - try { - unsigned short base = 0; - { - Genode::Attached_io_mem_dataspace io_mem(env, 0, 0x1000); - local = io_mem.local_addr(); - if (local) - base = (*reinterpret_cast(local + 0x40e)) << 4; - } - - if (!base) - return 0; - - Genode::Attached_io_mem_dataspace io_mem(env, base, 1024); - local = _search_rsdp(io_mem.local_addr()); - - if (local) - return base + (local - io_mem.local_addr()); - } catch (...) { - Genode::warning("failed to scan EBDA for RSDP root"); - } - - return 0; - } - - public: - - Acpi_table() { } - - Genode::addr_t phys_rsdp() - { - Genode::uint64_t phys_rsdp = _rsdp(); - return phys_rsdp; - } -}; - -ACPI_PHYSICAL_ADDRESS AcpiOsGetRootPointer (void) -{ - Genode::Acpi_table acpi_table; - ACPI_PHYSICAL_ADDRESS rsdp = acpi_table.phys_rsdp(); - return rsdp; -}