From f62fbefe5448fd90281e0c76378861e289ab669c Mon Sep 17 00:00:00 2001 From: "Justin C. Miller" Date: Mon, 16 Apr 2018 23:56:03 -0700 Subject: [PATCH] Parse APIC addresses out of ACPI tables. --- src/modules/main/acpi_tables.h | 22 ++++++++---- src/modules/main/device_manager.cpp | 53 ++++++++++++++++++++++++++++- src/modules/main/device_manager.h | 10 ++++++ 3 files changed, 77 insertions(+), 8 deletions(-) diff --git a/src/modules/main/acpi_tables.h b/src/modules/main/acpi_tables.h index 64e094b..d50fa88 100644 --- a/src/modules/main/acpi_tables.h +++ b/src/modules/main/acpi_tables.h @@ -25,13 +25,6 @@ struct acpi_table_header acpi_table_header header; -struct acpi_xsdt -{ - TABLE_HEADER('XSDT'); - acpi_table_header *headers[0]; -} __attribute__ ((packed)); - - template bool acpi_validate(const T *t) { return t->header.validate(T::type_id); } @@ -41,3 +34,18 @@ size_t acpi_table_entries(const T *t, size_t size) return (t->header.length - sizeof(T)) / size; } + +struct acpi_xsdt +{ + TABLE_HEADER('XSDT'); + acpi_table_header *headers[0]; +} __attribute__ ((packed)); + +struct acpi_apic +{ + TABLE_HEADER('APIC'); + uint32_t local_address; + uint32_t flags; + uint8_t controller_data[0]; +} __attribute__ ((packed)); + diff --git a/src/modules/main/device_manager.cpp b/src/modules/main/device_manager.cpp index cdcdf85..1d95f42 100644 --- a/src/modules/main/device_manager.cpp +++ b/src/modules/main/device_manager.cpp @@ -47,7 +47,8 @@ acpi_table_header::validate(uint32_t expected_type) const return !expected_type || (expected_type == type); } -device_manager::device_manager(const void *root_table) +device_manager::device_manager(const void *root_table) : + m_local_apic(nullptr) { console *cons = console::get(); @@ -98,8 +99,58 @@ device_manager::load_xsdt(const acpi_xsdt *xsdt) cons->puts(" "); put_sig(cons, header->type); + kassert(header->validate(), "Table failed validation."); + + switch (header->type) { + case acpi_apic::type_id: + load_apic(reinterpret_cast(header)); + break; + + default: + break; + } } cons->puts("\n"); } + +template +T read_from(const uint8_t *p) { return *reinterpret_cast(p); } + +void +device_manager::load_apic(const acpi_apic *apic) +{ + console *cons = console::get(); + + m_local_apic = reinterpret_cast(apic->local_address); + cons->puts(" "); + cons->put_hex(apic->local_address); + + uint8_t const *p = apic->controller_data; + uint8_t const *end = p + acpi_table_entries(apic, 1); + + while (p < end) { + const uint8_t type = p[0]; + const uint8_t length = p[1]; + + cons->puts(" "); + cons->put_hex(type); + + switch (type) { + case 0: // Local APIC + break; + + case 1: // I/O APIC + m_io_apic = reinterpret_cast(read_from(p+4)); + m_global_interrupt_base = read_from(p+8); + cons->puts(" "); + cons->put_hex((uint64_t)m_io_apic); + cons->puts(" "); + cons->put_hex(m_global_interrupt_base); + break; + } + + p += length; + } +} diff --git a/src/modules/main/device_manager.h b/src/modules/main/device_manager.h index d8d9b62..5477ae4 100644 --- a/src/modules/main/device_manager.h +++ b/src/modules/main/device_manager.h @@ -1,6 +1,7 @@ #pragma once struct acpi_xsdt; +struct acpi_apic; class device_manager { @@ -10,6 +11,15 @@ public: device_manager() = delete; device_manager(const device_manager &) = delete; + uint8_t * local_apic() const; + uint8_t * io_apic() const; + private: + uint8_t *m_local_apic; + uint8_t *m_io_apic; + + uint32_t m_global_interrupt_base; + void load_xsdt(const acpi_xsdt *xsdt); + void load_apic(const acpi_apic *apic); };