fix/kernel: Started fixing bootstrap acpi parser
This commit is contained in:
parent
4151de51d9
commit
3b8639467f
3 changed files with 48 additions and 86 deletions
|
@ -171,5 +171,13 @@ void emk_entry(void)
|
||||||
acpi_init();
|
acpi_init();
|
||||||
log_early("Initialized ACPI");
|
log_early("Initialized ACPI");
|
||||||
|
|
||||||
|
void *madt = acpi_find_table("MADT");
|
||||||
|
if (!madt)
|
||||||
|
{
|
||||||
|
kpanic(NULL, "Failed to find MADT table");
|
||||||
|
}
|
||||||
|
|
||||||
|
log_early("Found MADT at %p", madt);
|
||||||
|
|
||||||
hlt();
|
hlt();
|
||||||
}
|
}
|
|
@ -8,31 +8,6 @@
|
||||||
static int acpi_uses_xsdt = 0;
|
static int acpi_uses_xsdt = 0;
|
||||||
static void *acpi_rsdt_ptr = NULL;
|
static void *acpi_rsdt_ptr = NULL;
|
||||||
|
|
||||||
static uint8_t acpi_checksum(void *ptr, size_t len)
|
|
||||||
{
|
|
||||||
uint8_t sum = 0;
|
|
||||||
uint8_t *data = (uint8_t *)ptr;
|
|
||||||
for (size_t i = 0; i < len; i++)
|
|
||||||
{
|
|
||||||
sum += data[i];
|
|
||||||
}
|
|
||||||
return sum;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int acpi_validate_rsdp(acpi_rsdp_t *rsdp)
|
|
||||||
{
|
|
||||||
return acpi_checksum(rsdp, sizeof(acpi_rsdp_t)) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int acpi_validate_xsdp(acpi_xsdp_t *xsdp)
|
|
||||||
{
|
|
||||||
if (acpi_checksum(xsdp, sizeof(acpi_rsdp_t)) != 0)
|
|
||||||
return 0;
|
|
||||||
if (acpi_checksum(xsdp, xsdp->length) != 0)
|
|
||||||
return 0;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void acpi_init(void)
|
void acpi_init(void)
|
||||||
{
|
{
|
||||||
if (!rsdp_response || !rsdp_response->address)
|
if (!rsdp_response || !rsdp_response->address)
|
||||||
|
@ -40,81 +15,47 @@ void acpi_init(void)
|
||||||
kpanic(NULL, "No RSDP provided");
|
kpanic(NULL, "No RSDP provided");
|
||||||
}
|
}
|
||||||
|
|
||||||
acpi_rsdp_t *rsdp = (acpi_rsdp_t *)rsdp_response->address;
|
acpi_rsdp_t *rsdp = (acpi_rsdp_t *)HIGHER_HALF(rsdp_response->address);
|
||||||
log_early("RSDP found at %p", rsdp);
|
if (memcmp(rsdp->signature, "RSD PTR", 7))
|
||||||
if (strncmp(rsdp->signature, "RSD PTR ", 8) != 0)
|
kpanic(NULL, "Invalid RSDP signature!");
|
||||||
{
|
|
||||||
kpanic(NULL, "Invalid RSDP signature");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rsdp->revision >= 2)
|
if (rsdp->revision != 0)
|
||||||
{
|
{
|
||||||
acpi_xsdp_t *xsdp = (acpi_xsdp_t *)rsdp;
|
|
||||||
if (!acpi_validate_xsdp(xsdp))
|
|
||||||
{
|
|
||||||
kpanic(NULL, "XSDP checksum validation failed");
|
|
||||||
}
|
|
||||||
acpi_uses_xsdt = 1;
|
acpi_uses_xsdt = 1;
|
||||||
acpi_rsdt_ptr = (void *)(uintptr_t)xsdp->xsdt_address;
|
acpi_xsdp_t *xsdp = (acpi_xsdp_t *)rsdp;
|
||||||
}
|
acpi_rsdt_ptr = (acpi_xsdt_t *)HIGHER_HALF(xsdp->xsdt_address);
|
||||||
else
|
log_early("XSDT found at %p", acpi_rsdt_ptr);
|
||||||
{
|
return;
|
||||||
if (!acpi_validate_rsdp(rsdp))
|
|
||||||
{
|
|
||||||
kpanic(NULL, "RSDP checksum validation failed");
|
|
||||||
}
|
|
||||||
acpi_uses_xsdt = 0;
|
|
||||||
acpi_rsdt_ptr = (void *)(uintptr_t)rsdp->rsdt_address;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Validate RSDT/XSDT header */
|
acpi_rsdt_ptr = (acpi_rsdt_t *)HIGHER_HALF(rsdp->rsdt_address);
|
||||||
acpi_sdt_header_t *sdt = (acpi_sdt_header_t *)acpi_rsdt_ptr;
|
log_early("RSDT found at %p", acpi_rsdt_ptr);
|
||||||
if (acpi_checksum(sdt, sdt->length) != 0)
|
|
||||||
{
|
|
||||||
kpanic(NULL, "RSDT/XSDT checksum validation failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
log_early("ACPI initialized, using %s at %p",
|
|
||||||
acpi_uses_xsdt ? "XSDT" : "RSDT", acpi_rsdt_ptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void *acpi_find_table(const char *name)
|
void *acpi_find_table(const char *name)
|
||||||
{
|
{
|
||||||
if (!acpi_rsdt_ptr || !name)
|
if (!acpi_uses_xsdt)
|
||||||
|
{
|
||||||
|
acpi_rsdt_t *rsdt = (acpi_rsdt_t *)acpi_rsdt_ptr;
|
||||||
|
uint32_t entries = (rsdt->sdt.length - sizeof(rsdt->sdt)) / 4;
|
||||||
|
for (uint32_t i = 0; i < entries; i++)
|
||||||
|
{
|
||||||
|
acpi_sdt_header_t *sdt = (acpi_sdt_header_t *)HIGHER_HALF(*((uint32_t *)rsdt->table + i));
|
||||||
|
if (!memcmp(sdt->signature, name, 4))
|
||||||
|
return (void *)sdt;
|
||||||
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
acpi_sdt_header_t *sdt = (acpi_sdt_header_t *)acpi_rsdt_ptr;
|
|
||||||
uint32_t entries;
|
|
||||||
|
|
||||||
if (acpi_uses_xsdt)
|
|
||||||
{
|
|
||||||
entries = (sdt->length - sizeof(acpi_sdt_header_t)) / sizeof(uint64_t);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
entries = (sdt->length - sizeof(acpi_sdt_header_t)) / sizeof(uint32_t);
|
|
||||||
}
|
}
|
||||||
|
acpi_xsdt_t *xsdt = (acpi_xsdt_t *)acpi_rsdt_ptr;
|
||||||
|
log_early("XSDT address: %p", xsdt);
|
||||||
|
uint32_t entries = (xsdt->sdt.length - sizeof(xsdt->sdt)) / 8;
|
||||||
|
|
||||||
for (uint32_t i = 0; i < entries; i++)
|
for (uint32_t i = 0; i < entries; i++)
|
||||||
{
|
{
|
||||||
acpi_sdt_header_t *table;
|
acpi_sdt_header_t *sdt = (acpi_sdt_header_t *)HIGHER_HALF(*((uint64_t *)xsdt->table + i));
|
||||||
if (acpi_uses_xsdt)
|
if (!memcmp(sdt->signature, name, 4))
|
||||||
{
|
{
|
||||||
uint64_t *xsdt_entries = (uint64_t *)(sdt + 1);
|
return (void *)sdt;
|
||||||
table = (acpi_sdt_header_t *)(uintptr_t)xsdt_entries[i];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
uint32_t *rsdt_entries = (uint32_t *)(sdt + 1);
|
|
||||||
table = (acpi_sdt_header_t *)(uintptr_t)rsdt_entries[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strncmp(table->signature, name, 4) == 0)
|
|
||||||
{
|
|
||||||
if (acpi_checksum(table, table->length) == 0)
|
|
||||||
{
|
|
||||||
return table;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,9 +22,10 @@ typedef struct acpi_xsdp
|
||||||
char oem_id[6];
|
char oem_id[6];
|
||||||
uint8_t revision;
|
uint8_t revision;
|
||||||
uint32_t rsdt_address;
|
uint32_t rsdt_address;
|
||||||
|
uint32_t resv;
|
||||||
uint32_t length;
|
uint32_t length;
|
||||||
uint64_t xsdt_address;
|
uint64_t xsdt_address;
|
||||||
uint8_t full_checksum;
|
uint8_t extended_checksum;
|
||||||
uint8_t reserved[3];
|
uint8_t reserved[3];
|
||||||
} __attribute__((packed)) acpi_xsdp_t;
|
} __attribute__((packed)) acpi_xsdp_t;
|
||||||
|
|
||||||
|
@ -41,6 +42,18 @@ typedef struct acpi_sdt_header
|
||||||
uint32_t creator_revision;
|
uint32_t creator_revision;
|
||||||
} __attribute__((packed)) acpi_sdt_header_t;
|
} __attribute__((packed)) acpi_sdt_header_t;
|
||||||
|
|
||||||
|
typedef struct acpi_rsdt
|
||||||
|
{
|
||||||
|
acpi_sdt_header_t sdt;
|
||||||
|
char table[];
|
||||||
|
} __attribute__((packed)) acpi_rsdt_t;
|
||||||
|
|
||||||
|
typedef struct acpi_xsdt
|
||||||
|
{
|
||||||
|
acpi_sdt_header_t sdt;
|
||||||
|
char table[];
|
||||||
|
} __attribute__((packed)) acpi_xsdt_t;
|
||||||
|
|
||||||
void *acpi_find_table(const char *name);
|
void *acpi_find_table(const char *name);
|
||||||
void acpi_init(void);
|
void acpi_init(void);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue