aboutsummaryrefslogtreecommitdiff
path: root/src/drivers/acpi.cc
blob: 9c252023c2d200324950e8f38a04ee9d5bbf56cc (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#include "acpi.hpp"
#include "core/paging.hpp"
#include "libs/stdio.hpp"
#include "libs/string.hpp"

RSDP rsdp;
RSDT rsdt;
IOAPIC ioapic;

char acpi_init(void* rsdp_p){
    printk("Init ACPI... ");

    // Load RSDP
    memcpy(rsdp_p, &rsdp, sizeof(rsdp));
    if(rsdp.signature!=ACPI_RSDP_SIGNATURE){
        printk("Invalid RSDP signature\n");
        return 1;
    }
    if(acpi_checksum(rsdp_p, 20)){
        printk("Wrong RSDP Signature\n");
        return 1;
    }
    printk("ACPI Revision %d detected. ",rsdp.revision);

    // Load sub tables
    if(acpi_load_rsdt())
        return 1;
    if(acpi_load_madt())
        return 1;
    print("\n");
    return 0;
}

char acpi_load_rsdt(){
    PAGING_MAP(rsdp.rsdt_addr); // Ensure page is accessible
    memcpy((void*)rsdp.rsdt_addr, &rsdt, sizeof(rsdt));
    rsdt.first_entry_addr_ptr=rsdp.rsdt_addr+36;
    if(rsdt.header.signature !=ACPI_RSDT_SIGNATURE){
        printk("Invalid RSDT signature\n");
        return 1;
    }
    if(acpi_checksum((void*)rsdp.rsdt_addr, rsdt.header.length)){
        printk("Wrong RSDT Signature\n");
        return 1;
    }
    printk("RSDT loaded. ");
    return 0;
}

char acpi_load_madt(){
    int n_entry=(rsdt.header.length-36)/4;
    // Locate MADT
    for(int i=0;i<n_entry;i++){
        u32 *addr=(u32*)(rsdt.first_entry_addr_ptr+i*4);
        // Load header
        ACPI_TABLE_HEADER header;
        PAGING_MAP(*addr);
        memcpy((void*)*addr, &header, sizeof(header));
        // Check if it is MADT
        if(header.signature==ACPI_MADT_SIGNATURE){
            printk("MADT  found. ");
            int int_ctrl_location=0;
            while(int_ctrl_location<(header.length-44)){
                u32 cur_addr=(*addr)+44+int_ctrl_location;
                INT_CTRL_HEADER int_header;
                memcpy((void*)cur_addr, &int_header, sizeof(int_header));
                if(int_header.type==1){
                    printk("APIC Detected.");
                    memcpy((void*)cur_addr, &ioapic, sizeof(ioapic));
                    return 0;
                }
                int_ctrl_location+=int_header.length;
            }

        }
    }
    return 1;
}

char acpi_checksum(void* p, char size){
    char checksum=0;
    char* data_p=(char*)p;
    for(int i=0;i<size;i++){
        checksum+=data_p[i];
    }
    return (checksum!=0);
}