mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 08:24: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;
|
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));
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user