Parse acpi data table
This commit is contained in:
133
src/kernel/cpu/acpi.c
Normal file
133
src/kernel/cpu/acpi.c
Normal file
@@ -0,0 +1,133 @@
|
||||
#include <cpu.h>
|
||||
#include <multiboot.h>
|
||||
#include <memory.h>
|
||||
#include <string.h>
|
||||
#include <debug.h>
|
||||
|
||||
// ACPI Specification https://uefi.org/sites/default/files/resources/ACPI_6_3_final_Jan30.pdf
|
||||
|
||||
struct rsdp // 5.2.5.3
|
||||
{
|
||||
char signature[8];
|
||||
uint8_t checksum;
|
||||
char OEMID[6];
|
||||
uint8_t revision;
|
||||
uint32_t rsdt_p;
|
||||
uint32_t length; // only if revision >= 2
|
||||
uint64_t xsdt_p; // only if revision >= 2
|
||||
uint8_t checksum2; // only if revision >= 2
|
||||
uint8_t reserved[3]; // only if revision >= 2
|
||||
}__attribute__((packed));
|
||||
|
||||
struct sdt_header // 5.2.6
|
||||
{
|
||||
char signature[4];
|
||||
uint32_t length;
|
||||
uint8_t revision;
|
||||
uint8_t checksum;
|
||||
char OEMID[6];
|
||||
char OEMtable[8];
|
||||
uint32_t OEMrevision;
|
||||
uint32_t creatorID;
|
||||
uint32_t creatorRevision;
|
||||
uint8_t data[];
|
||||
}__attribute__((packed));
|
||||
|
||||
struct madt_header // 5.2.12
|
||||
{
|
||||
uint32_t controllerAddress;
|
||||
uint32_t flags;
|
||||
uint8_t fields[];
|
||||
}__attribute__((packed));
|
||||
|
||||
struct madt_field
|
||||
{
|
||||
uint8_t type;
|
||||
uint8_t length;
|
||||
uint8_t data[];
|
||||
}__attribute__((packed));
|
||||
|
||||
// MADT field type: 0
|
||||
#define MADT_TYPE_LAPIC 0
|
||||
struct madt_data_lapic
|
||||
{ // 5.2.12.2
|
||||
uint8_t id;
|
||||
uint8_t apic;
|
||||
uint32_t flags;
|
||||
}__attribute__((packed));
|
||||
|
||||
// MADT field type: 1
|
||||
#define MADT_TYPE_IOAPIC 1
|
||||
struct madt_data_ioapic
|
||||
{ // 5.2.12.3
|
||||
uint8_t id;
|
||||
uint8_t reserved;
|
||||
uint32_t address;
|
||||
uint32_t base;
|
||||
}__attribute__((packed));
|
||||
|
||||
// MADT field type: 2
|
||||
#define MADT_TYPE_ISO 2
|
||||
struct madt_data_iso
|
||||
{ // 5.2.12.5
|
||||
uint8_t bus;
|
||||
uint8_t source;
|
||||
uint32_t interrupt;
|
||||
uint16_t flags;
|
||||
}__attribute__((packed));
|
||||
|
||||
|
||||
void acpi_parse()
|
||||
{
|
||||
int cpu_i=0;
|
||||
|
||||
struct rsdp *rsdp = kernel_boot_data.rsdp;
|
||||
struct sdt_header *rsdt = P2V(rsdp->rsdt_p);
|
||||
|
||||
uint32_t *table = (void *)rsdt->data;
|
||||
int entries = (rsdt->length - sizeof(struct sdt_header))/sizeof(uint32_t);
|
||||
for(int i = 0; i < entries; i++)
|
||||
{
|
||||
struct sdt_header *h = P2V(table[i]);
|
||||
if(h->length == 0) continue;
|
||||
|
||||
if(!strncmp(h->signature, "APIC", 4)) // 5.2.12
|
||||
{
|
||||
struct madt_header *madt = P2V(h->data);
|
||||
for(
|
||||
struct madt_field *f = (void *)madt->fields;
|
||||
(size_t)f <= (size_t)h + h->length;
|
||||
f = incptr(f, f->length)
|
||||
)
|
||||
{
|
||||
switch(f->type) {
|
||||
case MADT_TYPE_LAPIC:
|
||||
{
|
||||
struct madt_data_lapic *lapic = (void *)f->data;
|
||||
struct cpu *cpu = P2V(pmm_alloc());
|
||||
cpus[cpu_i++] = cpu;
|
||||
cpu->id = lapic->id;
|
||||
cpu->apic_id = lapic->apic;
|
||||
cpu->flags = lapic->flags;
|
||||
break;
|
||||
}
|
||||
case MADT_TYPE_IOAPIC:
|
||||
{
|
||||
struct madt_data_ioapic *_ioapic = (void *)f->data;
|
||||
ioapic.id = _ioapic->id;
|
||||
ioapic.addr = _ioapic->address;
|
||||
ioapic.base = _ioapic->base;
|
||||
break;
|
||||
}
|
||||
case MADT_TYPE_ISO:
|
||||
{
|
||||
struct madt_data_iso *iso = (void *)f->data;
|
||||
irq_redirects[iso->source] = iso->interrupt;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user