/* * This file controls the ACPI */ #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 *); /* 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]); } } }