Parse APIC addresses out of ACPI tables.

This commit is contained in:
Justin C. Miller
2018-04-16 23:56:03 -07:00
parent 6c29024eac
commit f62fbefe54
3 changed files with 77 additions and 8 deletions

View File

@@ -25,13 +25,6 @@ struct acpi_table_header
acpi_table_header header; acpi_table_header header;
struct acpi_xsdt
{
TABLE_HEADER('XSDT');
acpi_table_header *headers[0];
} __attribute__ ((packed));
template <typename T> template <typename T>
bool acpi_validate(const T *t) { return t->header.validate(T::type_id); } 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; 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));

View File

@@ -47,7 +47,8 @@ acpi_table_header::validate(uint32_t expected_type) const
return !expected_type || (expected_type == type); 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(); console *cons = console::get();
@@ -98,8 +99,58 @@ device_manager::load_xsdt(const acpi_xsdt *xsdt)
cons->puts(" "); cons->puts(" ");
put_sig(cons, header->type); put_sig(cons, header->type);
kassert(header->validate(), "Table failed validation."); kassert(header->validate(), "Table failed validation.");
switch (header->type) {
case acpi_apic::type_id:
load_apic(reinterpret_cast<const acpi_apic *>(header));
break;
default:
break;
}
} }
cons->puts("\n"); cons->puts("\n");
} }
template <typename T>
T read_from(const uint8_t *p) { return *reinterpret_cast<const T *>(p); }
void
device_manager::load_apic(const acpi_apic *apic)
{
console *cons = console::get();
m_local_apic = reinterpret_cast<uint8_t *>(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<uint8_t *>(read_from<uint32_t>(p+4));
m_global_interrupt_base = read_from<uint32_t>(p+8);
cons->puts(" ");
cons->put_hex((uint64_t)m_io_apic);
cons->puts(" ");
cons->put_hex(m_global_interrupt_base);
break;
}
p += length;
}
}

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
struct acpi_xsdt; struct acpi_xsdt;
struct acpi_apic;
class device_manager class device_manager
{ {
@@ -10,6 +11,15 @@ public:
device_manager() = delete; device_manager() = delete;
device_manager(const device_manager &) = delete; device_manager(const device_manager &) = delete;
uint8_t * local_apic() const;
uint8_t * io_apic() const;
private: 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_xsdt(const acpi_xsdt *xsdt);
void load_apic(const acpi_apic *apic);
}; };