From 9b22a6965579ea1867aea291d910c96f386b518b Mon Sep 17 00:00:00 2001 From: Brett Weiland Date: Tue, 24 Aug 2021 14:09:29 -0500 Subject: major backup 8.24.21 --- src/kernel/acpi.c | 179 +++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 145 insertions(+), 34 deletions(-) (limited to 'src/kernel/acpi.c') 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 #include #include +#include +#include +#include +#include +#include +#include +#include -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); } } - - -- cgit v1.2.3