Nucleus
Barry System headers (remove libc dependency) 18495cf (3 years, 2 months ago)
/*
* This file controls ACPI. It finds the ACPI Root System Descriptor Table then
* searches it for more tables, which can be initialised separately.
*/
#include <stdint.h>
#include <nucleus/kernel.h>
#include <nucleus/lib.h>
#include <nucleus/memory.h>
#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]);
}