From 0120df249e42f9f22d15bd761c6ca0e13dda9752 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Lov=C3=A9n?= Date: Sun, 20 Nov 2016 11:26:01 +0100 Subject: [PATCH] [BOOT] Parse multiboot information --- kernel/boot/boot.S | 16 +++++++ kernel/boot/kmain.c | 15 ++---- kernel/boot/multiboot.c | 94 ++++++++++++++++++++++++++++++++++++++ kernel/include/mem.h | 2 + kernel/include/multiboot.h | 63 +++++++++++++++++++++++++ 5 files changed, 179 insertions(+), 11 deletions(-) create mode 100644 kernel/boot/multiboot.c diff --git a/kernel/boot/boot.S b/kernel/boot/boot.S index e78ad57..03e7f8b 100644 --- a/kernel/boot/boot.S +++ b/kernel/boot/boot.S @@ -1,6 +1,13 @@ .intel_syntax noprefix #include +.section .data +// Some room to store the bootloader return values +MultiBootMagic: + .quad 0x0 +MultiBootData: + .quad 0x0 + // Some info from here: http://os.phil-opp.com/multiboot-kernel.html .section .text .global _start @@ -8,6 +15,9 @@ _start: cli + // Save eax and ebx in memory + mov V2P(MultiBootMagic), eax + mov V2P(MultiBootData), ebx // Check if long mode is available // Otherwise, there's no point in continuing @@ -74,6 +84,12 @@ long_mode_start: mov rax, 0x0 mov [V2P(BootP4)], rax + // Get the saved bootloader data and pass to kmain + movabs rax, MultiBootMagic + mov rdi, rax + movabs rax, MultiBootData + mov rsi, rax + // Call c kernel code .extern kmain call kmain diff --git a/kernel/boot/kmain.c b/kernel/boot/kmain.c index 26ed185..a529885 100644 --- a/kernel/boot/kmain.c +++ b/kernel/boot/kmain.c @@ -1,21 +1,14 @@ #include +#include +#include -int kmain(void) +int kmain(uint64_t multiboot_magic, void *multiboot_data) { debug_init(); debug_ok("MITTOS64 kernel booted\n"); debug_build_time(); debug_git_info(); - - // Test the printf functions - debug("binary:%b octal:%o dec:%d\n", 0xAA55, 0123, 456); - debug("hex:%x string:%s char:%c\n", 0xabcd, "Hello", 'T'); - debug("pointer:%x\n", kmain); - - debug_info("An information string\n"); - debug_ok("%s prints ok\n", "This string"); - debug_warning("A warning message\n"); - debug_error("%d is less than %x\n", 12, 17); + multiboot_init(multiboot_magic, P2V(multiboot_data)); debug_info("BOOT COMPLETE\n"); for(;;)asm("hlt"); diff --git a/kernel/boot/multiboot.c b/kernel/boot/multiboot.c new file mode 100644 index 0000000..b074e43 --- /dev/null +++ b/kernel/boot/multiboot.c @@ -0,0 +1,94 @@ +#include +#include +#include +#include + +struct mboot_data_st mboot_data; + + +void parse_multiboot1() +{ + mboot1_info *data = mboot_data.data; + if(data->flags & (1<<2)) + { + debug_ok("MBOOT1 - commandline\n"); + mboot_data.commandline = P2V(data->cmdline); + } + if(data->flags & (1<<9)) + { + debug_ok("MBOOT1 - bootloader\n"); + mboot_data.bootloader = P2V(data->bootloader_name); + } +} + +char *mboot_tags_type[] = { + "", // 0 + "Boot command line", // 1 + "Boot loader name", // 2 + "Module", // 3 + "Basic memory information", // 4 + "BIOS Boot device", // 5 + "Memory map", // 6 + "VBE info", // 7 + "Framebuffer info", // 8 + "ELF-Symbols", //9 + "APM table", // 10 + "EFI 32-bit system table pointer", // 11 + "EFI 64-bit system table pointer", // 12 + "SMBIOS tables", // 13 + "ACPI old RSDP", // 14 + "ACPI new RSDP", // 15 + "Networking information", // 16 + "EFI memory map", // 17 + "EFI boot services not terminated", +}; +void parse_multiboot2() +{ + mboot2_tags_head *data = mboot_data.data; + mboot2_tag_basic *tag = (void *)(data + 1); + while(tag->type != 0) + { + switch(tag->type) + { + case MBOOT2_CMDLINE: + mboot_data.commandline = tag->data; + debug_ok("MBOOT2 - handle "); + break; + case MBOOT2_BOOTLOADER: + mboot_data.bootloader = tag->data; + debug_ok("MBOOT2 - handle "); + break; + default: + debug_warning("MBOOT2 - ignore "); + break; + } + if(tag->type <= 18) + debug("%s (%d bytes)\n", mboot_tags_type[tag->type], tag->size); + else + debug("Unknown tag: %d (%d bytes)\n", tag->type, tag->size); + tag = next_tag(tag); + } +} + +void multiboot_init(uint64_t magic, void *data) +{ + mboot_data.data = data; + debug_info("MBOOT - Magic:%x\n", magic); + if(magic == MBOOT1_MAGIC2) + { + debug_info("MBOOT - Multiboot version 1\n"); + mboot_data.version = 1; + parse_multiboot1(); + } else if (magic == MBOOT2_MAGIC2) { + debug_info("MBOOT - Multiboot version 2\n"); + mboot_data.version = 2; + parse_multiboot2(); + } else { + debug_error("PANIC - NOT A MULTIBOOT COMPLIANT BOOTLOADER\n"); + for(;;); + } + if(mboot_data.commandline) + debug_info("MBOOT - Command line: %s\n", mboot_data.commandline); + if(mboot_data.bootloader) + debug_info("MBOOT - Bootloader: %s\n", mboot_data.bootloader); +} diff --git a/kernel/include/mem.h b/kernel/include/mem.h index 25bdcb6..c0d0fe1 100644 --- a/kernel/include/mem.h +++ b/kernel/include/mem.h @@ -13,6 +13,8 @@ #include #define V2P(a) ((uintptr_t)(a) - KERNEL_OFFSET) #define P2V(a) ((void *)((uintptr_t)(a) + KERNEL_OFFSET)) + // returns an address n bytes after the target of pointer p + #define incptr(p, n) ((void *)(((uintptr_t)(p)) + (n))) #endif // Paging diff --git a/kernel/include/multiboot.h b/kernel/include/multiboot.h index a80dc04..78c6152 100644 --- a/kernel/include/multiboot.h +++ b/kernel/include/multiboot.h @@ -12,3 +12,66 @@ #define MBOOT2_LENGTH (MultiBootHeaderEnd - MultiBootHeader) #define MBOOT2_CHECKSUM -(MBOOT2_MAGIC + MBOOT2_ARCH + MBOOT2_LENGTH) +#ifndef __ASSEMBLER__ +#include + +// MULTIBOOT 1 + typedef struct { + uint32_t flags; + uint32_t mem_lower; + uint32_t mem_upper; + uint32_t boot_device; + uint32_t cmdline; + uint32_t mods_count; + uint32_t mods_addr; + uint32_t symbol_num; + uint32_t symbol_size; + uint32_t symbol_addr; + uint32_t symbol_shndx; + uint32_t mmap_len; + uint32_t mmap_addr; + uint32_t drives_len; + uint32_t drives_addr; + uint32_t config_table; + uint32_t bootloader_name; + uint32_t apm_table; + uint32_t vbe_control_info; + uint32_t vbe_mode_info; + uint32_t vbe_mode; + uint32_t vbe_interface_seg; + uint32_t vbe_interface_off; + uint32_t vbe_interface_len; + } mboot1_info; + +// MULTIBOOT 2 + + typedef struct { + uint32_t total_size; + uint32_t reserved; + } mboot2_tags_head; + + typedef struct { + uint32_t type; + uint32_t size; + char data[]; + } mboot2_tag_basic; + + + #define MBOOT2_CMDLINE 1 + #define MBOOT2_BOOTLOADER 2 + + // Multiboot tags are padded to a multiple of 8 bytes + #define next_tag(tag) ((void *)((((uintptr_t)tag) + tag->size + 7) & ~0x7)) + + extern char *mboot_tags_type[]; + struct mboot_data_st{ + int version; + void *data; + char *commandline; + char *bootloader; + }; + extern struct mboot_data_st mboot_data; + + void multiboot_init(uint64_t magic, void *data); + +#endif