/* * This file controls ACPI. It finds the ACPI Root System Descriptor Table then * searches it for more tables, which can be initialised separately. */ #include #include #include #include #include "acpi.h" /* Root System Descriptor Pointer */ struct RSDPDesc { char signature[8]; uint8_t checksum; char oem[6]; uint8_t revision; uint32_t rsdt; } __attribute__((packed)); void init_apic(struct SDTHeader *); void init_fadt(struct SDTHeader *); void init_dsdt(struct SDTHeader *); /* Table handlers */ struct TableHandler { char *sig; void (*handler)(struct SDTHeader *); } handlers[] = { { "APIC", init_apic }, { "FACP", init_fadt }, { "DSDT", init_dsdt }, }; /* Match a signature to a handler */ void init_table(struct SDTHeader *table) { uint32_t i, check = 0; char *byte = (void *) table; set_page((uintptr_t) table, PAGE_ADDR((uintptr_t) table) | PTE_PRESENT | PTE_WRITE); flush_tlb((uintptr_t) table); /* Checksum */ for (i = 0; i < table->length; i++) check += byte[i]; if (check % 0x100) return; /* Match handler */ for (i = 0; i < sizeof(handlers) / sizeof(handlers[0]); i++) { if (memcmp(table->signature, handlers[i].sig, 4)) continue; handlers[i].handler(table); } } /* Initialise ACPI */ void init_acpi(void *ebda) { /* Search for Root System Descriptor Table */ char *sig; for (sig = ebda; sig < (char *) 0x100000; sig++) { if (!memcmp(sig, "RSD PTR ", 8)) break; } if (sig == (char *) 0x100000) return; /* RSDT checksum */ uint32_t i, check = 0; for (i = 0; i < sizeof(struct RSDPDesc); i++) check += sig[i]; if (check % 0x100) return; /* Iterate tables */ uint32_t j; struct SDTHeader *rsdt = (void *) ((struct RSDPDesc *) sig)->rsdt; struct SDTHeader **table = (void *) (rsdt + 1); set_page((uintptr_t) rsdt, PAGE_ADDR((uintptr_t) rsdt) | PTE_PRESENT | PTE_WRITE); flush_tlb((uintptr_t) rsdt); for (i = 0; i < (rsdt->length - sizeof(struct SDTHeader)) / 4; i++) init_table(table[i]); }