summaryrefslogtreecommitdiff
path: root/src/arch/amd64
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/amd64')
-rw-r--r--src/arch/amd64/mboot.c65
-rw-r--r--src/arch/amd64/mboot.h40
2 files changed, 105 insertions, 0 deletions
diff --git a/src/arch/amd64/mboot.c b/src/arch/amd64/mboot.c
new file mode 100644
index 0000000..a6ee465
--- /dev/null
+++ b/src/arch/amd64/mboot.c
@@ -0,0 +1,65 @@
+#include "mboot.h"
+
+#include <stddef.h>
+#include <lib.h>
+
+static void read_cmdline(struct mboot_info *info, struct mboot_tag *tag, char *data, uint8_t len) {
+ if (len >= CMDLINE_MAX)
+ len = CMDLINE_MAX; // truncate :(
+ memcpy(tag->data.cmdline, data, len);
+ tag->data.cmdline[len] = '\0';
+ info->tags[MBOOT_CMDLINE] = *tag;
+}
+
+static void read_xsdp(struct mboot_info *info, struct mboot_tag *tag, char *data) {
+ tag->data.rootsdp = (void *) data;
+ info->tags[MBOOT_XSDP] = *tag;
+}
+
+static uint32_t *read_tag(struct mboot_info *info, uint32_t *data) {
+ struct mboot_tag tag;
+ tag.type = ((uint16_t*)data)[0];
+ tag.size = data[1];
+ tag.valid = 1;
+
+ uint8_t data_len = tag.size - 2 * sizeof(uint32_t);
+
+ switch (tag.type) {
+ case MBOOT_CMDLINE:
+ read_cmdline(info, &tag, (char *)(data + 2), data_len);
+ break;
+ case MBOOT_XSDP:
+ read_xsdp(info, &tag, (char *) (data + 2));
+ break;
+ default:
+ break;
+ }
+
+ if(tag.size % 8 != 0) {
+ tag.size += 8 - (tag.size % 8);
+ }
+
+ return data + tag.size / sizeof(uint32_t);
+}
+
+struct mboot_info mboot_load_info(void *mboot_info) {
+ struct mboot_info info = {0};
+
+ uint32_t* data = (uint32_t*) mboot_info;
+ info.total_size = *data++;
+ info.reserved = *data++;
+
+ while((uint8_t*) data < (uint8_t*) mboot_info + info.total_size) {
+ data = read_tag(&info, data);
+ }
+
+ 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
new file mode 100644
index 0000000..88348f5
--- /dev/null
+++ b/src/arch/amd64/mboot.h
@@ -0,0 +1,40 @@
+#pragma once
+
+#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];
+ void *rootsdp;
+ } data;
+};
+
+enum mboot_tag_type {
+ MBOOT_CMDLINE = 0,
+ MBOOT_XSDP = 14
+};
+
+struct mboot_info {
+ uint32_t total_size;
+ uint32_t reserved;
+ struct mboot_tag tags[21];
+};
+
+/**
+ * Loads the multi boot information
+ * @param mboot_info - the pointer passed from multiboot2
+ */
+struct mboot_info mboot_load_info(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);