From 538d91ecf2419aef44b5656911f3881294e19743 Mon Sep 17 00:00:00 2001 From: Alexander Boettcher Date: Wed, 1 Aug 2018 15:19:06 +0200 Subject: [PATCH] hw/x86: ACPI tables parsing support Issue #2929 --- repos/base-hw/src/lib/hw/spec/x86_64/acpi.h | 120 ++++++++++++++++++++ 1 file changed, 120 insertions(+) create mode 100644 repos/base-hw/src/lib/hw/spec/x86_64/acpi.h diff --git a/repos/base-hw/src/lib/hw/spec/x86_64/acpi.h b/repos/base-hw/src/lib/hw/spec/x86_64/acpi.h new file mode 100644 index 0000000000..5682aafa6f --- /dev/null +++ b/repos/base-hw/src/lib/hw/spec/x86_64/acpi.h @@ -0,0 +1,120 @@ +/* + * \brief ACPI structures and parsing + * \author Alexander Boettcher + * \date 2018-04-23 + */ + +/* + * Copyright (C) 2018 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. + */ + +#ifndef _SRC__LIB__HW__SPEC__X86_64__ACPI_H_ +#define _SRC__LIB__HW__SPEC__X86_64__ACPI_H_ + +#include + +namespace Hw { + struct Acpi_generic; + struct Apic_madt; + + template + void for_each_rsdt_entry(Hw::Acpi_generic &, FUNC); + + template + void for_each_xsdt_entry(Hw::Acpi_generic &, FUNC); + + template + void for_each_apic_struct(Acpi_generic &, FUNC); +} + +/* ACPI spec 5.2.6 */ +struct Hw::Acpi_generic +{ + Genode::uint8_t signature[4]; + Genode::uint32_t size; + Genode::uint8_t rev; + Genode::uint8_t checksum; + Genode::uint8_t oemid[6]; + Genode::uint8_t oemtabid[8]; + Genode::uint32_t oemrev; + Genode::uint8_t creator[4]; + Genode::uint32_t creator_rev; + +} __attribute__((packed)); + +struct Hw::Apic_madt +{ + enum { LAPIC = 0, IO_APIC = 1 }; + + Genode::uint8_t type; + Genode::uint8_t length; + + Apic_madt *next() const { return reinterpret_cast((Genode::uint8_t *)this + length); } + + struct Ioapic : Genode::Mmio { + + struct Id : Register <0x02, 8> { }; + struct Paddr : Register <0x04, 32> { }; + struct Gsi_base : Register <0x08, 32> { }; + + Ioapic(Apic_madt const * a) : Mmio(reinterpret_cast(a)) { } + }; + + struct Lapic : Genode::Mmio { + + struct Flags : Register <0x04, 32> { enum { ENABLED = 1 }; }; + + Lapic(Apic_madt const * a) : Mmio(reinterpret_cast(a)) { } + }; + +} __attribute__((packed)); + +template +void Hw::for_each_rsdt_entry(Hw::Acpi_generic &rsdt, FUNC fn) +{ + if (Genode::memcmp(rsdt.signature, "RSDT", 4)) + return; + + typedef Genode::uint32_t entry_t; + + unsigned const table_size = rsdt.size; + unsigned const entry_count = (table_size - sizeof(rsdt)) / sizeof(entry_t); + + entry_t * entries = reinterpret_cast(&rsdt + 1); + for (unsigned i = 0; i < entry_count; i++) + fn(entries[i]); +} + +template +void Hw::for_each_xsdt_entry(Hw::Acpi_generic &xsdt, FUNC fn) +{ + if (Genode::memcmp(xsdt.signature, "XSDT", 4)) + return; + + typedef Genode::uint64_t entry_t; + + unsigned const table_size = xsdt.size; + unsigned const entry_count = (table_size - sizeof(xsdt)) / sizeof(entry_t); + + entry_t * entries = reinterpret_cast(&xsdt + 1); + for (unsigned i = 0; i < entry_count; i++) + fn(entries[i]); +} + +template +void Hw::for_each_apic_struct(Hw::Acpi_generic &apic_madt, FUNC fn) +{ + if (Genode::memcmp(apic_madt.signature, "APIC", 4)) + return; + + Apic_madt const * const first = reinterpret_cast(&apic_madt.creator_rev + 3); + Apic_madt const * const last = reinterpret_cast(reinterpret_cast(apic_madt.signature) + apic_madt.size); + + for (Apic_madt const * e = first; e < last ; e = e->next()) + fn(e); +} + +#endif /* _SRC__LIB__HW__SPEC__X86_64__ACPI_H_ */