summaryrefslogtreecommitdiff
path: root/src/kernel/acpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/kernel/acpi.c')
-rw-r--r--src/kernel/acpi.c179
1 files changed, 145 insertions, 34 deletions
diff --git a/src/kernel/acpi.c b/src/kernel/acpi.c
index 0c22fe4..e5a6e4d 100644
--- a/src/kernel/acpi.c
+++ b/src/kernel/acpi.c
@@ -1,58 +1,169 @@
#include <acpi.h>
#include <stdint.h>
#include <printf.h>
+#include <kernel.h>
+#include <stdbool.h>
+#include <kernel.h>
+#include <io.h>
+#include <int.h>
+#include <libc.h>
+#include <panic.h>
-static int RSDP_verify(void *rsdp_pointer) {
- printf("Verifying potential RSDP at address 0x%p... ", rsdp_pointer);
- union rsdp_t *rsdp = rsdp_pointer;
+
+//finding rsdp
+typedef struct rsdp {
+ char sig[8];
+ uint8_t checksum;
+ char OEMID[6];
+ uint8_t revision;
+ uint32_t rsdt;
+
+ //these only exist on REV > 1
+ uint32_t len;
+ uint64_t xsdt;
+ uint8_t extended_checksum;
+ uint8_t reserved[3];
+
+} __attribute__((packed)) root_sdp;
+
+
+//root descriptor SDTs
+struct rsdt {
+ sdt_head header;
+ uint32_t sdt_pointers[];
+} __attribute__((packed));
+
+struct xsdt {
+ sdt_head header;
+ uint64_t sdt_pointers[];
+} __attribute__((packed));
+
+root_sdp *rsdp;
+
+
+
+void debug_acpi() {
+ sdt_head *sdt;
+ int sdt_i, sdt_cnt;
+
+ if(rsdp->revision) {
+ struct xsdt *root = PHYS_TO_VIRT(rsdp->xsdt);
+ sdt_cnt = (root->header.length - sizeof(root->header)) / 8;
+ printf("sdts found in apic headers: %i\n", sdt_cnt);
+ for(sdt_i = 0; sdt_i < sdt_cnt; sdt_i++) {
+ sdt = PHYS_TO_VIRT(root->sdt_pointers[sdt_i]);
+ printf("ACPI debug:%.4s\n", sdt->sig);
+ }
+ }
+ else {
+ struct rsdt *root = PHYS_TO_VIRT((uint64_t)rsdp->rsdt);
+ sdt_cnt = (root->header.length - sizeof(root->header)) / 4;
+ printf("sdts found in apic headers: %i\n", sdt_cnt);
+ for(sdt_i = 0; sdt_i < sdt_cnt; sdt_i++) {
+ sdt = PHYS_TO_VIRT((uint64_t)root->sdt_pointers[sdt_i]);
+ printf("ACPI debug:%.4s\n", sdt->sig);
+ }
+ }
+}
+
+//TODO clean up confusing variable name rsdt
+void *find_sdt(int type) {
+ char sig[4];
+ sdt_head *sdt;
+ int sdt_i, sdt_cnt;
+
+ //If we never need to expand this, then you can clean it up.
+ switch(type) {
+ case SDT_MADT:
+ strcpy(sig, "APIC");
+ break;
+ case SDT_HPET:
+ strcpy(sig, "HPET");
+ break;
+ }
+
+ if(rsdp->revision) {
+ struct xsdt *root = PHYS_TO_VIRT(rsdp->xsdt);
+ sdt_cnt = (root->header.length - sizeof(root->header)) / 8;
+ for(sdt_i = 0; sdt_i < sdt_cnt - 1; sdt_i++) {
+ sdt = PHYS_TO_VIRT((uint64_t)root->sdt_pointers[sdt_i]);
+ if(!(strncmp(sdt->sig, sig, 4))) {
+ return sdt;
+ }
+ }
+ }
+ else {
+ struct rsdt *root = PHYS_TO_VIRT((uint64_t)rsdp->rsdt);
+ sdt_cnt = (root->header.length - sizeof(root->header)) / 4;
+ for(sdt_i = 0; sdt_i < sdt_cnt - 1; sdt_i++) {
+ sdt = PHYS_TO_VIRT((uint64_t)root->sdt_pointers[sdt_i]);
+ if(!(strncmp(sdt->sig, sig, 4))) {
+ return sdt;
+ }
+ }
+ }
+ return 0;
+}
+
+bool verify_sdt(sdt_head *sdt) {
uint8_t checksum = 0;
- char *rsdp_csm_ptr = rsdp_pointer;
+ for(int i = 0; i < sdt->length; i++) checksum += ((uint8_t *)sdt)[i];
+ return checksum == 0;
+}
+
+static root_sdp *verify_sdp(root_sdp *uv_rsdp) {
+ char *rsdp_char_ptr = (char *)uv_rsdp;
int i;
- if(checksum) return 0;
- if(rsdp->v1.version) {
- printf("APCI revision > 2.\n");
- checksum = 0;
- printf("len : %i\n", rsdp->v2.len);
- for(i = 0; i < rsdp->v2.len; i++) {
- checksum += rsdp_csm_ptr[i];
+ uint8_t checksum = 0;
+ if(uv_rsdp->revision) {
+ for(i = 0; i < uv_rsdp->len; i++) {
+ checksum += rsdp_char_ptr[i];
}
}
else {
- printf("APCI revision 1.\n");
for(i = 0; i <= 20; i++) {
- checksum += rsdp_csm_ptr[i];
+ checksum += rsdp_char_ptr[i];
}
}
- if(checksum) {
- return 0;
- printf("Invalid, searching on.\n");
+ if(!checksum) {
+ printf("Found RSDP revision %i at address %x.\n", uv_rsdp->revision, uv_rsdp);
+ return uv_rsdp;
}
- printf("RSDP Verified!\n");
- return 1;
+ printf("Skipped over invalid RSDP at 0x%p.\n", uv_rsdp);
+ return 0;
}
-rsdp_t *find_RSDP() {
+
+void find_root_sdp() {
const char sig[9] = "RSD PTR ";
uintptr_t *p = (void *)0x040e;
uintptr_t *ebda_unshifted = (void *)p;
+ bool rsdt_verified;
- void *ebda = (void *)((uintptr_t)ebda_unshifted << (uintptr_t)4 & (uintptr_t)0xfffff);
+ void *ebda = PHYS_TO_VIRT((void *)((uintptr_t)ebda_unshifted << (uintptr_t)4 & (uintptr_t)0xfffff));
- for(void *i = ebda; i <= ebda + 64000; i += 16) {
- if(!(memcmp(sig, i, 8))) {
- if(RSDP_verify(i)) {
- return(i);
- }
- }
+
+
+ for(void *i = ebda; i <= ebda + 64000; i += 16)
+ if(!(memcmp(sig, i, 8)) && ((rsdp = verify_sdp(i)))) break;
+
+
+ for(void *i = PHYS_TO_VIRT(0xe0000); i <= PHYS_TO_VIRT(0xfffff); i += 16)
+ if(!(memcmp(sig, i, 8)) && ((rsdp = verify_sdp(i)))) break;
+
+ if(!(rsdp)) {
+ printf("Couldn't find the RSDP... not sure what to do now.\n");
+ PANIC(KERNEL_PANIC_RSDP_UNFOUND);
+ }
+
+ if(rsdp->revision) {
+ rsdt_verified = verify_sdt(PHYS_TO_VIRT(rsdp->xsdt));
+ }
+ else {
+ rsdt_verified = verify_sdt(PHYS_TO_VIRT((uint64_t)rsdp->rsdt));
}
- for(void *i = (void *)0xe0000; i <= (void *)0xfffff; i += 16) {
- if(!(memcmp(sig, i, 8))) {
- if(RSDP_verify(i)) {
- return(i);
- }
- }
+ if(!(rsdt_verified)) {
+ PANIC(KERNEL_PANIC_INVALID_RSDT);
}
}
-
-