Nucleus
Barry ACPI + APIC 232d0f9 (3 years, 3 months ago)
/*
* This file controls the ACPI
*/
#include <stdint.h>
#include <string.h>
#include <nucleus/panic.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 *);
/* Table handlers */
struct TableHandler {
char *sig;
void (*handler)(struct SDTHeader *);
} handlers[] = {
{"APIC", init_apic},
};
/* Calculate the ACPI checksum */
static uint32_t
checksum(struct SDTHeader *header)
{
char *byte = (void *) header;
uint32_t i, check = 0;
for (i = 0; i < header->length; i++)
check += byte[i];
return ((check % 0x100) == 0);
}
/* 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);
for (i = 0; i < (rsdt->length - sizeof(struct SDTHeader)) / 4; i++) {
if (!checksum(table[i]))
continue;
/* Try to match to a handler */
for (j = 0; j < sizeof(handlers)/sizeof(handlers[0]); j++) {
if (memcmp(table[i]->signature, handlers[j].sig, 4))
continue;
handlers[j].handler(table[i]);
}
}
}