diff options
Diffstat (limited to 'kernel/acpi.c')
| -rw-r--r-- | kernel/acpi.c | 169 |
1 files changed, 169 insertions, 0 deletions
diff --git a/kernel/acpi.c b/kernel/acpi.c new file mode 100644 index 0000000..5879d05 --- /dev/null +++ b/kernel/acpi.c @@ -0,0 +1,169 @@ +#include "acpi.h" +#include "memops.h" +#include "kprintf.h" +#include "asm_inline.h" + +#include <stddef.h> + +void* getPointerToOtherSDT(ACPISDTHeader* header) +{ + uint8_t* base = (uint8_t*)header; + return &(base[36]); +} + +void* getACPITablesPointer(APICHeader* header) +{ + uint8_t* base = (uint8_t*)header; + return &(base[44]); +} + +#define IS_TABLE(x, header) kmemcmp(x, header->signature, 4*sizeof(uint8_t)) + +enum ACPI_TABLES getTableType(ACPISDTHeader* header) +{ + if(IS_TABLE("APIC", header)) return APIC; + if(IS_TABLE("BGRT", header)) return BGRT; + if(IS_TABLE("BERT", header)) return BERT; + if(IS_TABLE("CPEP", header)) return CPEP; + if(IS_TABLE("DSDT", header)) return DSDT; + if(IS_TABLE("ECDT", header)) return ECDT; + if(IS_TABLE("EINJ", header)) return EINJ; + if(IS_TABLE("ERST", header)) return ERST; + if(IS_TABLE("FACP", header)) return FACP; + if(IS_TABLE("FACS", header)) return FACS; + if(IS_TABLE("HEST", header)) return HEST; + if(IS_TABLE("MSCT", header)) return MSCT; + if(IS_TABLE("MPST", header)) return MPST; + if(IS_TABLE("OEMx", header)) return OEMx; + if(IS_TABLE("PMTT", header)) return PMTT; + if(IS_TABLE("PSDT", header)) return PSDT; + if(IS_TABLE("RASF", header)) return RASF; + if(IS_TABLE("RSDT", header)) return RSDT; + if(IS_TABLE("SBST", header)) return SBST; + if(IS_TABLE("SLIT", header)) return SLIT; + if(IS_TABLE("SRAT", header)) return SRAT; + if(IS_TABLE("SSDT", header)) return SSDT; + if(IS_TABLE("XSDT", header)) return XSDT; + if(IS_TABLE("HPET", header)) return HPET; + + return NONE; +} + +void* getTable(void* xsdt, enum ACPI_TABLES table) +{ + ACPISDTHeader* header = (ACPISDTHeader*)xsdt; + uint64_t* tables = (uint64_t*)getPointerToOtherSDT(xsdt); + uint64_t entries = (header->length - sizeof(ACPISDTHeader)) / 8; + + for(int i = 0; i < entries; i++) + { + uint64_t table_ptr = tables[i]; + + if(getTableType((ACPISDTHeader*)table_ptr) == table) + { + return (ACPISDTHeader*)table_ptr; + } + } + + return NULL; +} + +void* getAPIC(APICHeader* header, enum APIC_TYPE apic) +{ + header->length; + uint8_t* apic_tables = (uint8_t*)getACPITablesPointer(header); + APICEntry* entry = (APICEntry*)apic_tables; + uint8_t offset = 0; + + while(offset < (header->length - sizeof(APICHeader))) + { + APICEntry* entry = (APICEntry*)&(apic_tables[offset]); + if(entry->type == apic) + { + return entry; + } + + offset += entry->length; + } + + return NULL; +} + +uint64_t numberTables(APICHeader* header) +{ + header->length; + uint8_t* apic_tables = (uint8_t*)getACPITablesPointer(header); + APICEntry* entry = (APICEntry*)apic_tables; + uint8_t offset = 0; + uint64_t tables = 0; + + while(offset < (header->length - sizeof(APICHeader))) + { + /* + APICEntry* entry = (APICEntry*)&(apic_tables[offset]); + if(entry->type == apic) + { + return entry; + } + */ + + tables++; + offset += entry->length; + } + + return tables; +} + +void init_acpi(XSDP* xsdp) +{ + kprintf("=> Initializing ACPI\n"); + + uint64_t pic_master = inb(0x21); + uint64_t pic_slave = inb(0xA1); + + if((pic_master == 0xFF) && (pic_slave == 0xFF)) + { + kprintf("==> PIC disabled\n"); + } + + if(xsdp != NULL) + { + kprintf("==> ACPI 2.0 Found\n"); + } + else + { + kprintf("==X No ACPI 2.0 Found\n"); + return; + } + + ACPISDTHeader* xsdt = (ACPISDTHeader*)xsdp->xsdtaddress; + + APICHeader* apic_table = (APICHeader*)getTable(xsdt, APIC); + if(apic_table == NULL) + { + kprintf("==X Failed To Find APIC Table\n"); + return; + } + + kprintf("==> Found APIC Table\n"); + if(apic_table->flags >= 0) + { + kprintf("==> Dual 8259 PIC Found\n"); + } + + IOAPICTable* ioapic = getAPIC(apic_table, IOAPIC); + if(ioapic == NULL) + { + kprintf("==X Failed to find a valid IOAPIC\n"); + return; + } + + uint64_t n_tables = numberTables(apic_table); + + kprintf("Number of Tables: %ld\n", n_tables); + + kprintf("==> IOAPIC Found\n"); + + + // kprintf("=> ACPI Initialized\n"); +} |
