diff --git a/include/acpi.h b/include/acpi.h index 99a446c..4c5c7b1 100644 --- a/include/acpi.h +++ b/include/acpi.h @@ -1,13 +1,5 @@ #pragma once -enum acpi_status { - ACPI_SUCCESS = 0, - ACPI_FAILURE = -1, - ACPI_MALFORMED_TABLE = -2, - ACPI_OLD_VERSION = -4, - ACPI_S5_PARSE_ERROR = -5, -}; - /** * Loads the ACPI tables * https://en.wikipedia.org/wiki/ACPI diff --git a/include/shim.h b/include/shim.h index a0f0156..f3835ba 100644 --- a/include/shim.h +++ b/include/shim.h @@ -2,6 +2,10 @@ #include +#define CMDLINE_MAX 32 + struct boot_info { struct memory_map *map; + void *acpi_table; + char cmdline[CMDLINE_MAX]; }; diff --git a/src/arch/amd64/acpi.c b/src/arch/amd64/acpi.c index eb150fe..61083f4 100644 --- a/src/arch/amd64/acpi.c +++ b/src/arch/amd64/acpi.c @@ -5,6 +5,7 @@ #include #include "bindings.h" +#include "serial.h" /* global state, idk a better way rn */ struct acpi_state state; @@ -21,7 +22,18 @@ struct acpi_header { uint32_t creator_revision; }; +// root system descriptor pointer +// ACPI 1.0 +struct rsdp { + char signature[8]; + uint8_t checksum; + char oemid[6]; + uint8_t revision; + uint32_t rsdt_addr; +} __attribute__((packed)); + // eXtended system descriptor pointer +// ACPI 2.0 struct xsdp { char signature[8]; uint8_t checksum; @@ -35,13 +47,21 @@ struct xsdp { uint8_t reserved[3]; } __attribute__((packed)); +// root system descriptor table +// ACPI 1.0 +struct rsdt { + struct acpi_header h; + uint64_t sdt_pointers[]; +}; // eXtended system descriptor table +// ACPI 2.0 struct xsdt { struct acpi_header h; uint64_t sdt_pointers[]; }; + // generic address structure struct gas { uint8_t address_space; @@ -56,10 +76,10 @@ struct fadt { struct acpi_header h; uint32_t firmware_ctrl; uint32_t dsdt; - + // field used in ACPI 1.0; no longer in use, for compatibility only uint8_t reserved; - + uint8_t preferred_power_management_profile; uint16_t sci_interrupt; uint32_t smi_command_port; @@ -92,23 +112,23 @@ struct fadt { uint8_t day_alarm; uint8_t month_alarm; uint8_t century; - + // reserved in ACPI 1.0; used since ACPI 2.0+ uint16_t boot_architecture_flags; - + uint8_t reserved_2; uint32_t flags; - + // 12 byte structure; see below for details struct gas reset_reg; - + uint8_t reset_value; uint8_t reserved_3[3]; - + // 64bit pointers - Available on ACPI 2.0+ uint64_t x_firmware_control; uint64_t x_dsdt; - + struct gas x_pm1_a_event_block; struct gas x_pm1_b_event_block; struct gas x_pm1_a_control_block; @@ -135,9 +155,11 @@ static bool checksum(uint8_t *data, size_t len) { } static int read_s5_addr(struct acpi_state *state) { + serial_out_str("a"); uintptr_t ptr = state->fadt.dsdt; char *s5_addr = (void*) (ptr + 36); - + serial_out_str("a"); + int dsdt_len = *((int*) (ptr+1)) - 36; while (0 < dsdt_len--) { if ( memcmp(s5_addr, "_S5_", 4) == 0) @@ -164,17 +186,29 @@ static int read_s5_addr(struct acpi_state *state) { state->SCI_EN = 1; } else { - return ACPI_S5_PARSE_ERROR; + return -1; } } else { - return ACPI_S5_PARSE_ERROR; + return -1; } - return ACPI_SUCCESS; + return -1; } +static void *acpi_find_table_rsdt(struct rsdt *rsdt, const char *identifier, int ident_len) { + int entries = (rsdt->h.length - sizeof(rsdt->h)) / 8; -static void *acpi_find_table(struct xsdt *xsdt, const char *identifier, int ident_len) { + for (int i = 0; i < entries; i++) { + struct acpi_header *h = (struct acpi_header *) (uintptr_t) rsdt->sdt_pointers[i]; + if (!strncmp(h->signature, identifier, ident_len)) + return (void *)h; + } + + // TABLE NOT FOUND + return NULL; +} + +static void *acpi_find_table_xsdt(struct xsdt *xsdt, const char *identifier, int ident_len) { int entries = (xsdt->h.length - sizeof(xsdt->h)) / 8; for (int i = 0; i < entries; i++) { @@ -187,38 +221,72 @@ static void *acpi_find_table(struct xsdt *xsdt, const char *identifier, int iden return NULL; } -int acpi_init(void *rootsdp) { - struct xsdp *xsdp = (struct xsdp *) rootsdp; +int acpi_init_rsdt(struct rsdt *rsdt) { + if (!checksum((uint8_t *) &rsdt->h, rsdt->h.length)) + return -1; - if (!checksum((uint8_t *)xsdp, sizeof(struct xsdp))) - return ACPI_MALFORMED_TABLE; - - if (xsdp->revision != 2) - return ACPI_OLD_VERSION; - - struct xsdt *xsdt = (struct xsdt *) (uintptr_t) xsdp->xsdt_addr; - if (!checksum((uint8_t *) &xsdt->h, xsdt->h.length)) - return ACPI_MALFORMED_TABLE; - - struct fadt *fadt = acpi_find_table(xsdt, "FACP", 4); + struct fadt *fadt = acpi_find_table_rsdt(rsdt, "FACP", 4); if (!fadt) - return ACPI_MALFORMED_TABLE; + return -1; if (!checksum((uint8_t *) &fadt->h, fadt->h.length)) - return ACPI_MALFORMED_TABLE; + return -1; state.fadt = *fadt; + return -1; +} + +int acpi_init_xsdt(struct xsdt *xsdt) { + 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; +} + +int acpi_init(void *rootsdp) { + struct rsdp *rsdp = (struct rsdp *) rootsdp; + + if (!checksum((uint8_t *)rsdp, sizeof(struct xsdp))) + return -1; + + int res; + + if (rsdp->revision == 0) { + res = acpi_init_rsdt( + (struct rsdt *) (uintptr_t) rsdp->rsdt_addr + ); + } else if (rsdp->revision == 2) { + struct xsdp *xsdp = (struct xsdp *) rsdp; + res = acpi_init_xsdt( + (struct xsdt *) (uintptr_t) xsdp->xsdt_addr + ); + } else { + return -1; + } + + if (res) + return res; + int ret = read_s5_addr(&state); if (!ret) return ret; outb(state.fadt.smi_command_port,state.fadt.acpi_enable); - return ACPI_SUCCESS; + return 0; } int acpi_shutdown(void) { outw((unsigned int) state.fadt.pm1_a_control_block, state.SLP_TYPb | state.SLP_EN); - return ACPI_FAILURE; + return -1; } diff --git a/src/arch/amd64/mboot.c b/src/arch/amd64/mboot.c index 9d06fd0..68c9383 100644 --- a/src/arch/amd64/mboot.c +++ b/src/arch/amd64/mboot.c @@ -1,80 +1,72 @@ #include "mboot.h" #include "serial.h" +#include "shim.h" -#include #include -static void read_cmdline(struct mboot_tag *tag, char *data, uint8_t len) { +enum mboot_tag_type { + MBOOT_CMDLINE = 0, + MBOOT_MEMORYMAP = 6, + MBOOT_SYMBOLS = 9, + MBOOT_XSDP = 14 +}; + +static void read_cmdline(struct boot_info *shim_info, char *data, uint8_t len) { if (len >= CMDLINE_MAX) len = CMDLINE_MAX; // truncate :( - memcpy(tag->data.cmdline, data, len); - tag->data.cmdline[len] = '\0'; + memcpy(shim_info->cmdline, data, len); + shim_info->cmdline[len] = '\0'; } -static void read_memorymap(struct mboot_tag *tag, uint64_t size, uint32_t *data) { - tag->data.memory_map = (struct memory_map *) data; - tag->data.memory_map->size = size; +static void read_memorymap(struct boot_info *shim_info, uint64_t size, uint32_t *data) { + shim_info->map = (struct memory_map *) data; + shim_info->map->size = size; } -static void read_xsdp(struct mboot_tag *tag, char *data) { - tag->data.rootsdp = (void *) data; +static void read_xsdp(struct boot_info *shim_info, char *data) { + shim_info->acpi_table = (void *) data; } -static uint32_t *read_tag(struct mboot_info *info, uint32_t *data) { - struct mboot_tag tag; - tag.type = *((uint16_t *)data); - tag.size = data[1]; - tag.valid = 1; +static uint32_t *read_tag(uint32_t *data, struct boot_info *shim_info) { - uint8_t data_len = tag.size - 2 * sizeof(uint32_t); + uint16_t type = *((uint16_t *)data); + uint32_t size = data[1]; - switch (tag.type) { + uint8_t data_len = size - 2 * sizeof(uint32_t); + + switch (type) { case MBOOT_CMDLINE: - read_cmdline(&tag, (char *)(data + 2), data_len); + read_cmdline(shim_info, (char *)(data + 2), data_len); break; case MBOOT_MEMORYMAP: - read_memorymap(&tag, tag.size, data + 2); + read_memorymap(shim_info, size, data + 2); break; case MBOOT_SYMBOLS: // TODO: - goto done; + break; case MBOOT_XSDP: - read_xsdp(&tag, (char *) (data + 2)); + read_xsdp(shim_info, (char *) (data + 2)); break; default: - goto done; + break; } -done: - - info->tags[tag.type] = tag; - - if(tag.size % 8 != 0) { - tag.size += 8 - (tag.size % 8); + if(size % 8 != 0) { + size += 8 - (size % 8); } - return data + tag.size / sizeof(uint32_t); + return data + size / sizeof(uint32_t); } -struct mboot_info mboot_load_info(const void *mboot_info) { - struct mboot_info info = {0}; - +void mboot_load_info( + const void *mboot_info, + struct boot_info *shim_info +) { uint32_t* data = (uint32_t*) mboot_info; - info.total_size = *data++; - info.reserved = *data++; - + uint32_t total_size = *data++; + data++; //reserved - while((uint8_t*) data < (uint8_t*) mboot_info + info.total_size) { - data = read_tag(&info, data); + while((uint8_t*) data < (uint8_t*) mboot_info + total_size) { + data = read_tag(data, shim_info); } - - return info; -} - -struct mboot_tag *mboot_get_tag(struct mboot_info *info, enum mboot_tag_type type) { - if (info->tags[type].valid) { - return &info->tags[type]; - } else { - return NULL; - } } diff --git a/src/arch/amd64/mboot.h b/src/arch/amd64/mboot.h index 3be3054..90ed75c 100644 --- a/src/arch/amd64/mboot.h +++ b/src/arch/amd64/mboot.h @@ -1,44 +1,11 @@ #pragma once -#include "memory.h" -#include - -#define CMDLINE_MAX 32 - -struct mboot_tag { - uint8_t valid; // if the tag at this location is set - uint32_t type; - uint32_t size; - union { - char cmdline[CMDLINE_MAX + 1]; - struct memory_map *memory_map; - void *rootsdp; - } data; -}; - -enum mboot_tag_type { - MBOOT_CMDLINE = 0, - MBOOT_MEMORYMAP = 6, - MBOOT_SYMBOLS = 9, - MBOOT_XSDP = 14 -}; - -struct mboot_info { - uint32_t total_size; - uint32_t reserved; - struct mboot_tag tags[22]; -}; +#include +#include /** * Loads the multi boot information * @param mboot_info - the pointer passed from multiboot2 + * @param shim_info - the info to be collected by shim */ -struct mboot_info mboot_load_info(const void *mboot_info); - -/** - * Gets a tag from multiboot - * @param type - the tag type - * @returns NULL - tag not loaded - * @returns tag - tag was loaded - */ -struct mboot_tag *mboot_get_tag(struct mboot_info *info, enum mboot_tag_type type); +void mboot_load_info(const void *mboot_info, struct boot_info *shim_info); diff --git a/src/arch/amd64/shim.c b/src/arch/amd64/shim.c index 9a5be02..7332994 100644 --- a/src/arch/amd64/shim.c +++ b/src/arch/amd64/shim.c @@ -12,22 +12,14 @@ static struct boot_info boot_info; void* amd64_shim(void *mboot_data_ptr) { - + serial_init(); paging_init(); pic_remap(); idt_init(); - //kmap_page(mboot_data_ptr, mboot_data_ptr, F_WRITEABLE); - - struct mboot_info mboot_info; - mboot_info = mboot_load_info(mboot_data_ptr); + mboot_load_info(mboot_data_ptr, &boot_info); - struct mboot_tag *map_tag; - map_tag = mboot_get_tag(&mboot_info, MBOOT_MEMORYMAP); - - boot_info.map = map_tag->data.memory_map; - return &boot_info; } diff --git a/src/kmain.c b/src/kmain.c index b55b6a5..a1a7e7c 100644 --- a/src/kmain.c +++ b/src/kmain.c @@ -1,3 +1,4 @@ +#include "acpi.h" #include #include #include @@ -30,10 +31,19 @@ void print_memory() { void kmain(struct boot_info *info) { memory_init(info->map); + + int i = acpi_init(info->acpi_table); + char buf[20]; + ltoa(i, buf, 10); + serial_out_str("acpi: "); + serial_out_str(buf); + serial_out_str("\n"); + serial_out_str("entered kmain\n"); *(char*)(0xB8000 + 0x144) = 'h'; *(char*)(0xB8000 + 0x146) = 'i'; //fb_init(1024, 768); + acpi_shutdown(); while (1) { // loop so we dont halt // this allows interrupts to fire