#include #include #include #include // ACPI Specification: // https://uefi.org/sites/default/files/resources/ACPI_6_3_final_Jan30.pdf struct rsdp { // 5.2.5.3 char signature[8]; uint8_t checksum; char OEMID[6]; uint8_t revision; uint32_t rsdt_p; uint8_t _[14]; // Fields for revision >= 2 }__attribute__((packed)); struct sdt { char signature[4]; uint32_t length; uint8_t _[28]; uint32_t data[]; }__attribute__((packed)); // MADT (5.2.12) #define MADT_TYPE_LAPIC 0 #define MADT_TYPE_IOAPIC 1 #define MADT_TYPE_ISO 2 struct madt_field { uint8_t type; uint8_t length; union { struct { // Processor Local APIC (5.2.12.2) uint8_t id; uint8_t apic; uint32_t flags; }__attribute__((packed)) lapic; struct { // I/O APIC (5.2.12.3) uint8_t id; uint8_t reserved; uint32_t address; uint32_t base; }__attribute__((packed)) ioapic; struct { // Interrupt source override (5.2.12.5) uint8_t bus; uint8_t source; uint32_t interrupt; uint16_t flags; }__attribute__((packed)) iso; }; }__attribute__((packed)); struct madt_header { uint32_t controllerAddress; uint32_t flags; struct madt_field fields[]; }__attribute__((packed)); static void madt_parse(struct madt_header *madt, size_t length) { int cpu_i=0; for(struct madt_field *f = madt->fields; (size_t)f <= (size_t)madt + length; f = incptr(f, f->length) ) { switch(f->type) { case MADT_TYPE_LAPIC: { struct cpu *cpu = P2V(pmm_alloc()); cpus[cpu_i++] = cpu; cpu->id = f->lapic.id; cpu->apic_id = f->lapic.apic; cpu->flags = f->lapic.flags; break; } case MADT_TYPE_IOAPIC: { ioapic.id = f->ioapic.id; ioapic.addr = f->ioapic.address; ioapic.base = f->ioapic.base; break; } case MADT_TYPE_ISO: { irq_redirects[f->iso.source] = f->iso.interrupt; break; } default: } } } void acpi_parse(void *_rsdp) { struct rsdp *rsdp = _rsdp; struct sdt *rsdt = P2V(rsdp->rsdt_p); int rsdt_entries = (rsdt->length - sizeof(struct sdt))/sizeof(uint32_t); for(int i = 0; i < rsdt_entries; i++) { struct sdt *h = P2V(rsdt->data[i]); if(h->length == 0) continue; if(!strncmp(h->signature, "APIC", 4)) { // 5.2.12 madt_parse(P2V(h->data), h->length - sizeof(struct sdt)); } } }