aboutsummaryrefslogtreecommitdiff
path: root/kernel/multiboot2.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/multiboot2.c')
-rw-r--r--kernel/multiboot2.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/kernel/multiboot2.c b/kernel/multiboot2.c
new file mode 100644
index 0000000..bd6250f
--- /dev/null
+++ b/kernel/multiboot2.c
@@ -0,0 +1,50 @@
+#include "mmap.h"
+
+#define ADDR(x) ((unsigned)&x - 0xc0000000 + 0x2000)
+
+boot_info_t info __attribute__((section(".init")));
+
+__attribute__((section(".multiboot.text"))) void
+multiboot_strncpy(char *dest, const char *src, unsigned n)
+{
+ unsigned i;
+ for (i = 0; i < n && src[i] != '\0'; ++i) dest[i] = src[i];
+}
+
+__attribute__((section(".multiboot.text"))) void
+multiboot2_module(struct multiboot_tag_module *tag, boot_info_t *tag_info)
+{
+ tag_info->module_start = tag->mod_start;
+ tag_info->module_end = tag->mod_end;
+ multiboot_strncpy(tag_info->module_cmdline, tag->cmdline, 64);
+}
+
+/**
+ * parse multiboot2 structures
+ */
+__attribute__((section(".multiboot.text"))) void
+__multiboot2(multiboot_uint32_t addr)
+{
+ boot_info_t *__info = (boot_info_t *)ADDR(info);
+
+ struct multiboot_tag *tag;
+ for (tag = (struct multiboot_tag *)(addr + 8); tag->type != MULTIBOOT_TAG_TYPE_END;
+ tag = (struct multiboot_tag *)((multiboot_uint8_t *)tag + ((tag->size + 7u) & ~7u))) {
+
+ switch (tag->type) {
+ case MULTIBOOT_TAG_TYPE_CMDLINE:
+ multiboot_strncpy(__info->cmdline, ((struct multiboot_tag_string *)tag)->string, 64);
+ break;
+ case MULTIBOOT_TAG_TYPE_MODULE:
+ multiboot2_module((struct multiboot_tag_module *)tag, __info);
+ break;
+ case MULTIBOOT_TAG_TYPE_MMAP:
+ multiboot2_mmap(((struct multiboot_tag_mmap *)tag)->entries,
+ ((struct multiboot_tag_mmap *)tag)->size / ((struct multiboot_tag_mmap *)tag)->entry_size,
+ __info->bitmap);
+ break;
+ default:
+ break;
+ }
+ }
+}