razzle/kernel/rsdp.c

113 lines
2.8 KiB
C

#pragma once
#include <stdint.h>
#include "memory.c"
#include "vga.c"
struct rsdp_t {
char signature[8];
uint8_t checksum;
char oem_id[6];
uint8_t revision;
uint32_t rsdt_address;
} __attribute__ ((packed));
struct xsdp_t {
char signature[8];
uint8_t checksum;
char oem_id[6];
uint8_t revision;
uint32_t unused;
uint32_t length;
uint32_t xsdt_addr_hi;
uint32_t xsdt_addr_lo;
uint8_t checksum_ext;
uint8_t unused_[3];
} __attribute__ ((packed));
struct acpi_header_t {
char signature[4];
uint32_t length;
uint8_t revision;
uint8_t checksum;
char oem_id[6];
char oem_table_id[8];
uint32_t oem_revision;
uint32_t creator_id;
uint32_t creator_division;
} __attribute__ ((packed));
struct rsdt_t {
struct acpi_header_t header;
uint32_t pointer[64];
};
uint8_t validate(struct rsdp_t *ptr) {
char sig[] = "RSD PTR ";
if (!memseq(ptr->signature, sig, 8)) return 0;
uint8_t *rsdp_bytes = (uint8_t *) ptr;
uint8_t sum = 0;
for(uint8_t i = 0; i < 20; i++) {
sum += rsdp_bytes[i];
}
if (sum == 0 && ptr->revision == 2) {
printf_nolock("acpi: ACPI v2+ not yet supported :(\n");
for(;;){}
// TODO: test with ACPI 2 System
struct xsdp_t *r2_ptr = (struct xsdp_t*) ptr;
uint8_t *xsdp_bytes = ((uint8_t *) r2_ptr) + 8;
for(uint8_t i = 0; i < 16; i++) {
sum += xsdp_bytes[i];
}
}
return sum == 0;
}
char* find_table(struct rsdt_t* table, char* sig) {
uint32_t entries = (table->header.length - sizeof table->header) / 4;
for (uint32_t i = 0; i < entries; i++) {
struct acpi_header_t* entry = (struct acpi_header_t*) table->pointer[i];
if (memseq(entry->signature, sig, 4)) {
printf_nolock("Found %s / %s\n", entry->oem_id, entry->signature);
printf_nolock("Signature: %s\n", entry->signature);
printf_nolock("Length : %d\n", entry->length);
printf_nolock("Oem ID : %s\n", entry->oem_id);
printf_nolock("Checksum : %d\n", entry->checksum);
return (void*)entry;
}
}
printf_nolock("Not Found");
return 0;
}
void find_rsdp() {
struct rsdp_t *ptr;
volatile uint8_t found = 0;
for (uint32_t addr = 0x00000000; addr <= 0x000FFFFF; addr++) {
ptr = (struct rsdp_t *) addr;
if (validate(ptr)) {
found = 1;
break;
}
}
if (!found) {
uint8_t* ebda = (uint8_t*)(*((uint16_t*)0x40e) << 4);
for (uint32_t i = 0; i <= 1024; i += 16) {
ptr = (struct rsdp_t*) ebda;
if (validate(ptr)) {
found = 1;
break;
}
}
}
printf_nolock("acpi: RSDP Found [OEM: %s, SIG: %s]\n", ptr->oem_id, ptr->signature);
}