summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2024-01-30 16:46:38 -0500
committerFreya Murphy <freya@freyacat.org>2024-01-30 16:46:38 -0500
commit9cc8dfcf0eed77b536b1f81f0660c84777b2a0a8 (patch)
tree01cc5fad4c42b0fcad206e694c69567de835447b
parentbetter qemu options (diff)
downloadcorn-9cc8dfcf0eed77b536b1f81f0660c84777b2a0a8.tar.gz
corn-9cc8dfcf0eed77b536b1f81f0660c84777b2a0a8.tar.bz2
corn-9cc8dfcf0eed77b536b1f81f0660c84777b2a0a8.zip
better mboot
-rw-r--r--include/acpi.h8
-rw-r--r--include/shim.h4
-rw-r--r--src/arch/amd64/acpi.c120
-rw-r--r--src/arch/amd64/mboot.c84
-rw-r--r--src/arch/amd64/mboot.h41
-rw-r--r--src/arch/amd64/shim.c12
-rw-r--r--src/kmain.c10
7 files changed, 152 insertions, 127 deletions
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 <memory.h>
+#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 <stddef.h>
#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;
+
+ 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;
- if (!checksum((uint8_t *)xsdp, sizeof(struct xsdp)))
- return ACPI_MALFORMED_TABLE;
+ state.fadt = *fadt;
- if (xsdp->revision != 2)
- return ACPI_OLD_VERSION;
+ return -1;
+}
- struct xsdt *xsdt = (struct xsdt *) (uintptr_t) xsdp->xsdt_addr;
+int acpi_init_xsdt(struct xsdt *xsdt) {
if (!checksum((uint8_t *) &xsdt->h, xsdt->h.length))
- return ACPI_MALFORMED_TABLE;
+ return -1;
- struct fadt *fadt = acpi_find_table(xsdt, "FACP", 4);
+ struct fadt *fadt = acpi_find_table_xsdt(xsdt, "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 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 <stddef.h>
#include <lib.h>
-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) {
+
+ uint16_t type = *((uint16_t *)data);
+ uint32_t size = data[1];
- uint8_t data_len = tag.size - 2 * sizeof(uint32_t);
+ uint8_t data_len = size - 2 * sizeof(uint32_t);
- switch (tag.type) {
+ 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 <stdint.h>
-
-#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 <shim.h>
+#include <memory.h>
/**
* 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);
-
- struct mboot_tag *map_tag;
- map_tag = mboot_get_tag(&mboot_info, MBOOT_MEMORYMAP);
+ mboot_load_info(mboot_data_ptr, &boot_info);
- 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 <memory.h>
#include <lib.h>
#include <serial.h>
@@ -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