mirror of
https://github.com/justinian/jsix.git
synced 2025-12-09 16:04:32 -08:00
Parse APIC addresses out of ACPI tables.
This commit is contained in:
@@ -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 <typename T>
|
||||
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));
|
||||
|
||||
|
||||
@@ -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<const acpi_apic *>(header));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user