summaryrefslogtreecommitdiff
path: root/src/arch/amd64/mboot.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/arch/amd64/mboot.c')
-rw-r--r--src/arch/amd64/mboot.c65
1 files changed, 65 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;
+ }
+}