acpi table loading and shutdown works, plus mmap fix :3

This commit is contained in:
Freya Murphy 2024-02-03 21:38:57 -05:00
parent 85a9443704
commit 61e7fdf1eb
Signed by: freya
GPG key ID: 744AB800E383AE52
5 changed files with 140 additions and 126 deletions

View file

@ -9,12 +9,12 @@
#include "bindings.h"
struct acpi_header {
char signature[4];
uint32_t signature;
uint32_t length;
uint8_t revision;
uint8_t checksum;
char oem_id[6];
char oem_table_id[8];
uint8_t oem_id[6];
uint8_t oem_table_id[8];
uint32_t oem_revision;
uint32_t creator_id;
uint32_t creator_revision;
@ -23,9 +23,9 @@ struct acpi_header {
// root system descriptor pointer
// ACPI 1.0
struct rsdp {
char signature[8];
uint8_t signature[8];
uint8_t checksum;
char oemid[6];
uint8_t oemid[6];
uint8_t revision;
uint32_t rsdt_addr;
} __attribute__((packed));
@ -38,11 +38,12 @@ struct xsdp {
char oemid[6];
uint8_t revision;
uint32_t rsdt_addr;
uint32_t length;
uint64_t xsdt_addr;
uint8_t extendeid_checksum;
uint8_t reserved[3];
struct {
uint32_t length;
uint64_t xsdt_addr;
uint8_t extendeid_checksum;
uint8_t reserved[3];
} ext;
} __attribute__((packed));
// root system descriptor table
@ -50,14 +51,14 @@ struct xsdp {
struct rsdt {
struct acpi_header h;
uint32_t sdt_pointers[];
};
} __attribute__((packed));
// eXtended system descriptor table
// ACPI 2.0
struct xsdt {
struct acpi_header h;
uint64_t sdt_pointers[];
};
} __attribute__((packed));
// generic address structure
@ -69,6 +70,27 @@ struct gas {
uint64_t address;
};
// differentiated system description table
struct dsdt {
struct acpi_header h;
char s5_addr[];
} __attribute__((packed));
struct apic {
struct acpi_header h;
// todo
} __attribute__((packed));
struct hept {
struct acpi_header h;
// todo
} __attribute__((packed));
struct waet {
struct acpi_header h;
// todo
} __attribute__((packed));
// fixed acpi description table
struct fadt {
struct acpi_header h;
@ -135,15 +157,20 @@ struct fadt {
struct gas x_pm_timer_block;
struct gas x_gpe0_block;
struct gas x_gpe1_block;
};
} __attribute__((packed));
struct acpi_state {
union {
struct xsdt *xsdt;
struct rsdt *rsdt;
} dst;
} sdt;
struct fadt *fadt;
struct dsdt *dsdt;
struct apic *apic;
struct hept *hept;
struct waet *waet;
uint8_t version;
struct fadt fadt;
uint16_t SLP_TYPa;
uint16_t SLP_TYPb;
uint16_t SLP_EN;
@ -160,11 +187,10 @@ static bool checksum(uint8_t *data, size_t len) {
return sum == 0;
}
static int read_s5_addr(struct acpi_state *state) {
uintptr_t ptr = state->fadt.dsdt;
char *s5_addr = (void *) (ptr + 36);
static int read_s5_addr(struct dsdt *dsdt) {
char *s5_addr = dsdt->s5_addr;
int dsdt_len = dsdt->h.length - sizeof(struct acpi_header);
int dsdt_len = *((int *) (ptr+1)) - 36;
while (0 < dsdt_len--) {
if (memcmp(s5_addr, "_S5_", 4) == 0)
break;
@ -179,15 +205,15 @@ static int read_s5_addr(struct acpi_state *state) {
if (*s5_addr == 0x0A)
s5_addr++; // skip byteprefix
state->SLP_TYPa = *(s5_addr)<<10;
state.SLP_TYPa = *(s5_addr)<<10;
s5_addr++;
if (*s5_addr == 0x0A)
s5_addr++; // skip byteprefix
state->SLP_TYPb = *(s5_addr)<<10;
state.SLP_TYPb = *(s5_addr)<<10;
state->SLP_EN = 1<<13;
state->SCI_EN = 1;
state.SLP_EN = 1<<13;
state.SCI_EN = 1;
} else {
return -1;
@ -199,129 +225,115 @@ static int read_s5_addr(struct acpi_state *state) {
return -1;
}
static void *acpi_find_table_rsdt(struct rsdt *rsdt, const char *identifier, int ident_len) {
static void acpi_load_table(uint64_t addr);
static void acpi_load_rsdt_tables(struct rsdt *rsdt) {
int entries = (rsdt->h.length - sizeof(rsdt->h)) / 4;
for (int i = 0; i < entries; i++) {
struct acpi_header *h = (struct acpi_header *) (uintptr_t) rsdt->sdt_pointers[i];
char buf[6];
memcpy(buf, h->signature, 4);
buf[4] = '\n';
buf[5] = '\0';
kputs(buf);
if (!strncmp(h->signature, identifier, ident_len))
return (void *)h;
uint32_t addr = rsdt->sdt_pointers[i];
acpi_load_table(addr);
}
// TABLE NOT FOUND
return NULL;
}
static void *acpi_find_table_xsdt(struct xsdt *xsdt, const char *identifier, int ident_len) {
static void acpi_load_xsdt_tables(struct xsdt *xsdt) {
int entries = (xsdt->h.length - sizeof(xsdt->h)) / 8;
for (int i = 0; i < entries; i++) {
struct acpi_header *h = (struct acpi_header *) (uintptr_t) xsdt->sdt_pointers[i];
if (!strncmp(h->signature, identifier, ident_len))
return (void *)h;
uint64_t addr = xsdt->sdt_pointers[i];
acpi_load_table(addr);
}
// TABLE NOT FOUND
return NULL;
}
int acpi_init_rsdt(struct rsdt *rsdt) {
#define SIG_RSDT 0x54445352
#define SIG_XSDT 0x54445358
#define SIG_FACP 0x50434146
#define SIG_DSDT 0x54445344
#define SIG_APIC 0x43495041
#define SIG_HEPT 0x54455048
#define SIG_WAET 0x54454157
kprintf("RSDT: %#016lx\n", (size_t)rsdt);
rsdt = mmap(rsdt, sizeof(struct rsdt));
state.dst.rsdt = rsdt;
state.version = 0;
if (!checksum((uint8_t *) &rsdt->h, rsdt->h.length))
return -1;
struct fadt *fadt = acpi_find_table_rsdt(rsdt, "FACP", 4);
if (!fadt)
return -1;
if (!checksum((uint8_t *) &fadt->h, fadt->h.length))
return -1;
state.fadt = *fadt;
return -1;
static void acpi_handle_table(struct acpi_header *header) {
switch (header->signature) {
case SIG_RSDT:
state.sdt.rsdt = (struct rsdt *) header;
acpi_load_rsdt_tables(state.sdt.rsdt);
break;
case SIG_XSDT:
state.sdt.xsdt = (struct xsdt *) header;
acpi_load_xsdt_tables(state.sdt.xsdt);
break;
case SIG_FACP:
state.fadt = (struct fadt *) header;
acpi_load_table(state.fadt->dsdt);
break;
case SIG_DSDT:
state.dsdt = (struct dsdt *) header;
read_s5_addr(state.dsdt);
break;
case SIG_APIC:
state.apic = (struct apic *) header;
break;
case SIG_HEPT:
state.hept = (struct hept *) header;
break;
case SIG_WAET:
state.waet = (struct waet *) header;
break;
default:
break;
}
}
int acpi_init_xsdt(struct xsdt *xsdt) {
static void acpi_load_table(uint64_t addr) {
struct acpi_header *temp, *mapped;
uint32_t length;
xsdt = mmap(xsdt, sizeof(struct xsdt));
return -1;
state.dst.xsdt = xsdt;
state.version = 2;
if (!checksum((uint8_t *) &xsdt->h, xsdt->h.length))
return -1;
struct fadt *fadt = acpi_find_table_xsdt(xsdt, "FACP", 4);
if (!fadt)
return -1;
if (!checksum((uint8_t *) &fadt->h, fadt->h.length))
return -1;
state.fadt = *fadt;
return 0;
temp = (struct acpi_header * ) (uintptr_t) addr;
mapped = mmap(temp, sizeof(struct acpi_header));
length = mapped->length;
unmap(mapped);
mapped = mmap(temp, length);
if (!checksum((uint8_t *) mapped, mapped->length)) {
unmap(mapped);
return;
}
kprintf("%.*s: %#016lx\n", 4, (char*)&mapped->signature, (size_t)temp);
acpi_handle_table(mapped);
}
int acpi_init(void *rootsdp) {
memset(&state, 0, sizeof(struct acpi_state));
struct rsdp *rsdp = (struct rsdp *) rootsdp;
if (!checksum((uint8_t *)rsdp, sizeof(struct rsdp)))
return -1;
if (strncmp(rsdp->signature, "RSD PTR ", 8) != 0) {
if (memcmp(rsdp->signature, "RSD PTR ", 8) != 0) {
panic("invalid acpi rsdp signature: %.*s\n", 8, rsdp->signature);
}
int res;
if (rsdp->revision == 0) {
state.version = 0;
kprintf("ACPI 1.0\n");
kprintf("RSDP: %#016lx\n", (size_t)rsdp);
res = acpi_init_rsdt(
(struct rsdt *) (uintptr_t) rsdp->rsdt_addr
);
acpi_load_table(rsdp->rsdt_addr);
} else if (rsdp->revision == 2) {
state.version = 2;
struct xsdp *xsdp = (struct xsdp *) rsdp;
kprintf("ACPI 2.0\n");
kprintf("XSDP: %#016lx\n", (size_t)xsdp);
res = acpi_init_xsdt(
(struct xsdt *) (uintptr_t) xsdp->xsdt_addr
);
acpi_load_table(xsdp->ext.xsdt_addr);
} else {
panic("invalid acpi rev: %d\n", rsdp->revision);
}
if (res) {
kprintf("...acpi failed to load\n\n");
return res;
}
kprintf("\n");
kprintf("\n\n");
int ret = read_s5_addr(&state);
if (!ret)
return ret;
outb(state.fadt.smi_command_port,state.fadt.acpi_enable);
outb(state.fadt->smi_command_port,state.fadt->acpi_enable);
return 0;
}
int acpi_shutdown(void) {
outw((unsigned int) state.fadt.pm1_a_control_block, state.SLP_TYPb | state.SLP_EN);
outw((unsigned int) state.fadt->pm1_a_control_block, state.SLP_TYPb | state.SLP_EN);
return -1;
}

View file

@ -135,7 +135,7 @@ void idt_exception_handler(uint64_t exception, uint64_t code, struct isr_regs *s
kprintf("Error code 0x%lX\n", code);
if (exception == EX_PAGE_FAULT) {
kprintf("Page fault address: 0x%lX\n", cr2);
kprintf("Page fault address: %#016lx\n", cr2);
}
kputs("\n");

View file

@ -539,20 +539,20 @@ void paging_init(void) {
static inline void *page_align(void *addr) {
uintptr_t a = (uintptr_t) addr;
a += PAGE_SIZE - 1;
a /= PAGE_SIZE;
a *= PAGE_SIZE;
return (void *) a;
}
void *mmap(void *addr, size_t len) {
len += (long)addr % PAGE_SIZE;
long pages = (len + PAGE_SIZE - 1) / PAGE_SIZE;
void *phys = page_align(addr);
ptrdiff_t error = (char*)addr - (char*)phys;
len += error;
long pages = len / PAGE_SIZE + 1;
void *virt = virtaddr_alloc(pages);
if (virt == NULL) {
return NULL;
}
void *phys = page_align(addr);
if (map_pages(
kernel_pml4,
virt,
@ -563,7 +563,7 @@ void *mmap(void *addr, size_t len) {
virtaddr_free(virt);
return NULL;
}
return virt;
return (char*)virt + error;
}
void unmap(void *addr) {

View file

@ -15,12 +15,12 @@ void kmain(struct boot_info *info) {
kprintf("enterd kmain\n");
//acpi_shutdown();
// pages are allocated on write :3
char *test = kalloc(5);
*test = 1;
//log_backtrace();
while (1) {
screen_redraw();
// loop so we dont halt

View file

@ -95,6 +95,7 @@ static enum printtype conversion_to_printtype(enum format_conversion conversion)
return OCTAL;
case FMT_HEX:
case FMT_HEX_UPPER:
case FMT_PTR:
return HEX;
default:
return NONE;
@ -377,11 +378,12 @@ static void print_number_buffer(
const char *buf, // buffer containing the text we want to print
struct spacing spacing, // the spacing on the left right and middle
enum printtype type,
enum charcase cc
enum charcase cc,
enum format_flag flags
) {
// put the 0x at the start of the string
if (spacing.left && spacing.zero && type == HEX) {
if (spacing.left && spacing.zero && type == HEX && (flags & FLG_ALTERNATE)) {
if (cc == UPPERCASE) {
kputs("0X");
} else {
@ -389,7 +391,7 @@ static void print_number_buffer(
}
}
if ((!spacing.left || !spacing.zero) && type == OCTAL) {
if ((!spacing.left || !spacing.zero) && type == OCTAL && (flags & FLG_ALTERNATE)) {
kputc('0');
}
@ -397,7 +399,7 @@ static void print_number_buffer(
spacing.zero ? kputc('0') : kputc(' ');
}
if ((!spacing.left || !spacing.zero) && type == HEX) {
if ((!spacing.left || !spacing.zero) && type == HEX && (flags & FLG_ALTERNATE)) {
if (cc == UPPERCASE) {
kputs("0X");
} else {
@ -457,18 +459,18 @@ static struct spacing get_spacing(
}
unsigned gap = 0;
if (max > length) {
gap = max - length;
if (min > length) {
gap = min - length;
}
spacing.length = length;
if (flags & FLG_LEFT_ALIGN) {
spacing.left = gap;
spacing.right = 0;
} else {
spacing.left = 0;
spacing.right = gap;
} else {
spacing.left = gap;
spacing.right = 0;
}
spacing.zero = (flags & FLG_ZERO);
@ -574,7 +576,7 @@ static void print_signed_number(
unsigned length = strlen(ptr);
struct spacing spacing =
get_spacing(width, precision, flags, length);
print_number_buffer(ptr, spacing, type, cc);
print_number_buffer(ptr, spacing, type, cc, flags);
}
static void print_unsigned_number(
@ -591,7 +593,7 @@ static void print_unsigned_number(
unsigned length = strlen(ptr);
struct spacing spacing =
get_spacing(width, precision, flags, length);
print_number_buffer(ptr, spacing, type, cc);
print_number_buffer(ptr, spacing, type, cc, flags);
}
static bool is_conversion_number(enum format_conversion conversion) {