From 61e7fdf1eb7d5d4a66c443fe6bd16fd2a2a92859 Mon Sep 17 00:00:00 2001 From: Freya Murphy Date: Sat, 3 Feb 2024 21:38:57 -0500 Subject: [PATCH] acpi table loading and shutdown works, plus mmap fix :3 --- src/arch/amd64/acpi.c | 226 +++++++++++++++++++++------------------ src/arch/amd64/cpu/idt.c | 2 +- src/arch/amd64/paging.c | 10 +- src/kmain.c | 4 +- src/print.c | 24 +++-- 5 files changed, 140 insertions(+), 126 deletions(-) diff --git a/src/arch/amd64/acpi.c b/src/arch/amd64/acpi.c index eb38f73..59e9621 100644 --- a/src/arch/amd64/acpi.c +++ b/src/arch/amd64/acpi.c @@ -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; } diff --git a/src/arch/amd64/cpu/idt.c b/src/arch/amd64/cpu/idt.c index 3e98b55..464bdb0 100644 --- a/src/arch/amd64/cpu/idt.c +++ b/src/arch/amd64/cpu/idt.c @@ -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"); diff --git a/src/arch/amd64/paging.c b/src/arch/amd64/paging.c index a80737c..c857d0b 100644 --- a/src/arch/amd64/paging.c +++ b/src/arch/amd64/paging.c @@ -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) { diff --git a/src/kmain.c b/src/kmain.c index b4ebadb..07165bc 100644 --- a/src/kmain.c +++ b/src/kmain.c @@ -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 diff --git a/src/print.c b/src/print.c index 8cab6e4..a7ce5f6 100644 --- a/src/print.c +++ b/src/print.c @@ -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) {