summaryrefslogtreecommitdiffhomepage
path: root/src/loader/protocols/mb2.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/loader/protocols/mb2.c')
-rw-r--r--src/loader/protocols/mb2.c105
1 files changed, 105 insertions, 0 deletions
diff --git a/src/loader/protocols/mb2.c b/src/loader/protocols/mb2.c
new file mode 100644
index 0000000..8f0a660
--- /dev/null
+++ b/src/loader/protocols/mb2.c
@@ -0,0 +1,105 @@
+// MIT License, Copyright (c) 2021 Marvin Borner
+// Everything according to spec
+
+#include <elf.h>
+#include <protocols/mb2.h>
+#include <library.h>
+#include <panic.h>
+
+// The address where data gets stored
+#define MB2_LOAD_ADDRESS 0x10000
+
+struct mb2_entry {
+ u32 magic;
+ u32 flags;
+ u32 header_length;
+ u32 checksum; // Everything after that is optional
+ u8 *tags;
+};
+
+// The (really simple) multiboot checksum algorithm
+/* static u32 mb2_checksum(struct mb2_entry *entry) */
+/* { */
+/* return -(entry->magic + entry->flags); */
+/* } */
+
+// Load data into memory and return address (not overlapping
+static u32 mb2_store(void *data, u32 size)
+{
+ static u32 offset = 0;
+ memcpy((void *)MB2_LOAD_ADDRESS, data, size);
+ offset += size;
+ return MB2_LOAD_ADDRESS + (size - offset);
+}
+
+// Load the mb2 structs into memory
+static void mb2_load(struct mb2_entry *entry)
+{
+ (void)mb2_store;
+ (void)entry;
+}
+
+// Jump to kernel with correct info pointer in eax
+static void mb2_jump(u32 entry, u32 info)
+{
+ log("Jumping. So long and thanks for all the fish!\n");
+
+ // Move and jump!
+ __asm__ volatile("movl $" STRINGIFY(MB2_LOAD_MAGIC) ", %%eax\n\t"
+ "jmpl *%%edi\n\t"
+ :
+ : "D"(entry), "b"(info)
+ : "memory");
+
+ panic("Jumper returned\n");
+}
+
+// Detect and verify mb2
+u8 mb2_detect(struct config_entry *cfg)
+{
+ u8 header[8192] = { 0 };
+
+ s32 ret = cfg->dev->p.disk.fs.read(cfg->path, header, 0, sizeof(header), cfg->dev);
+ if (ret < 12)
+ return 0;
+
+ // Find start of multiboot entry by searching for magic
+ struct mb2_entry *entry = 0;
+ for (u32 i = 0; i < sizeof(header); i++) {
+ u32 *p = (u32 *)&header[i];
+ if (*p == MB2_MAGIC) {
+ entry = (void *)p;
+ break;
+ }
+ }
+
+ if (!entry)
+ return 0;
+
+ // TODO: mb2 checksum
+ /* u32 checksum = mb2_checksum(entry); */
+ /* if (checksum != entry->checksum) */
+ /* return 0; */
+
+ cfg->impl.type = IMPL_MB2;
+ cfg->impl.offset = (u32)entry - (u32)header;
+
+ return 1;
+}
+
+// Execute mb2 type kernel
+void mb2_exec(struct config_entry *cfg)
+{
+ struct mb2_entry mb2_entry = { 0 };
+ s32 ret = cfg->dev->p.disk.fs.read(cfg->path, &mb2_entry, cfg->impl.offset,
+ sizeof(mb2_entry), cfg->dev);
+ assert(ret == sizeof(mb2_entry));
+ mb2_load(&mb2_entry);
+
+ u32 entry = elf_load(cfg->dev, cfg->path);
+
+ // This is a kind of hacky parameter stack pushing thing, just disable warning :)
+#pragma GCC diagnostic ignored "-Wpedantic"
+ jmp_kernel((void *)mb2_jump, 2, entry, MB2_LOAD_ADDRESS);
+#pragma GCC diagnostic pop
+}