#include #include #include #include #include #include #include #include #include #include //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; 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; uint8_t checksum = 0; if(uv_rsdp->revision) { for(i = 0; i < uv_rsdp->len; i++) { checksum += rsdp_char_ptr[i]; } } else { for(i = 0; i <= 20; i++) { checksum += rsdp_char_ptr[i]; } } if(!checksum) { printf("Found RSDP revision %i at address %x.\n", uv_rsdp->revision, uv_rsdp); return uv_rsdp; } printf("Skipped over invalid RSDP at 0x%p.\n", uv_rsdp); return 0; } 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 = 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)) && ((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)); } if(!(rsdt_verified)) { PANIC(KERNEL_PANIC_INVALID_RSDT); } }