From ca42990b55d428c2d1b81bf55ef139c206a5ae65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20Lov=C3=A9n?= Date: Mon, 3 Jan 2022 15:25:12 +0100 Subject: [PATCH] Process multiboot data --- src/kernel/boot/boot.S | 3 ++ src/kernel/boot/kmain.c | 42 ++++++++------- src/kernel/boot/multiboot.c | 98 ++++++++++++++++++++++++++++++++++ src/kernel/include/memory.h | 2 + src/kernel/include/multiboot.h | 22 ++++++++ 5 files changed, 149 insertions(+), 18 deletions(-) create mode 100644 src/kernel/boot/multiboot.c diff --git a/src/kernel/boot/boot.S b/src/kernel/boot/boot.S index 19f1d4f..76fedce 100644 --- a/src/kernel/boot/boot.S +++ b/src/kernel/boot/boot.S @@ -16,6 +16,9 @@ _start: cli + mov edi, eax + mov esi, ebx + // Temporary stack for booting mov esp, offset V2P(BootStack) diff --git a/src/kernel/boot/kmain.c b/src/kernel/boot/kmain.c index e7277e8..22140dd 100644 --- a/src/kernel/boot/kmain.c +++ b/src/kernel/boot/kmain.c @@ -1,33 +1,39 @@ +#include #include #include #include +#include -void clear_screen() -{ - unsigned char *vidmem = P2V(0xB8000); - for(int i=0; i < 80*24*2; i++) - *vidmem++ = 0; -} +struct kernel_boot_data_st kernel_boot_data; -void print_string(char *str) -{ - unsigned char *vidmem = P2V(0xB8000); - while(*str) - { - *vidmem++ = *str++; - *vidmem++ = 0x7; - } -} - -void kmain() +void kmain(uint64_t multiboot_magic, void *multiboot_data) { vga_init(); + + debug("Started kernel\n"); + + debug("Multiboot magic: %x", multiboot_magic); + multiboot_init(multiboot_magic, P2V(multiboot_data)); + + debug_info("Multiboot v %d kernel loaded.\n", kernel_boot_data.multiboot_version); + debug_info("Bootloader: %s\n", kernel_boot_data.bootloader); + + debug_info("Memory areas:\n"); + size_t index = 0; + uintptr_t start, end; + uint32_t type; + while(!multiboot_get_memory_ara(index, &start, &end, &type)) + { + debug_info("%d %x-%x\n", type, start, end); + index++; + } + debug("Hello, world!"); int value = 123; debug_info("dec: %d hex: %x, binary: %b", value, value, value); PANIC("End of kernel function!"); - debug_info("Broke out of panic") + debug_info("Broke out of panic"); for(;;); } \ No newline at end of file diff --git a/src/kernel/boot/multiboot.c b/src/kernel/boot/multiboot.c new file mode 100644 index 0000000..41a5e2e --- /dev/null +++ b/src/kernel/boot/multiboot.c @@ -0,0 +1,98 @@ +#include +#include +#include +#include + +// https://www.gnu.org/software/grub/manual/multiboot2/multiboot.html + +struct taglist { + uint32_t total_size; + uint32_t reserved; +}__attribute__((packed)); + +struct tag { + uint32_t type; + uint32_t size; + uint8_t data[]; +}__attribute__((packed)); + +struct mmap_entry { + uint64_t base; + uint64_t len; + uint32_t type; + uint32_t reserved; +}__attribute__((packed)); + +struct mmap { + uint32_t entry_size; + uint32_t entry_version; + struct mmap_entry entries[]; +}__attribute__((packed)); + +struct fbinfo { + uint64_t framebuffer_addr; + uint32_t framebuffer_pitch; + uint32_t framebuffer_width; + uint32_t framebuffer_height; + uint8_t framebuffer_bpp; + uint8_t framebuffer_type; + uint8_t reserved; + uint8_t data[]; +}__attribute__((packed)); + +int parse_multiboot2(struct taglist *tags) +{ + struct tag *tag = incptr(tags, sizeof(struct taglist)); + struct mmap *mmap; + while(tag->type) + { + debug("Tag type: %d\n", tag->type); + switch(tag->type) + { + case MBOOT2_TAG_BOOTLOADER: + kernel_boot_data.bootloader = (char *)tag->data; + break; + case MBOOT2_TAG_CMDLINE: + kernel_boot_data.commandline = (char *)tag->data; + break; + case MBOOT2_TAG_MMAP: + mmap = kernel_boot_data.mmap = (void *)tag->data; + kernel_boot_data.mmap_len = (tag->size - 8)/mmap->entry_size; + kernel_boot_data.mmap_size = (tag->size - 8); + break; + case 8: + break; + } + + int padded_size = tag->size + ((tag->size % 8)?(8-(tag->size%8)):0); + tag = incptr(tag, padded_size); + } + return 0; +} + +int multiboot_init(uint64_t magic, void *mboot_info) +{ + if(magic == MBOOT2_REPLY) + { + kernel_boot_data.multiboot_version = 2; + parse_multiboot2(mboot_info); + } + else + return 1; + + return 0; +} + +int multiboot_get_memory_ara(size_t index, uintptr_t *start, uintptr_t *end, uint32_t *type) +{ + if(index >= kernel_boot_data.mmap_len) return 1; + + struct mmap *mmap = kernel_boot_data.mmap; + struct mmap_entry *entry = mmap->entries; + entry = incptr(entry, index*mmap->entry_size); + + *start = entry->base; + *end = entry->base + entry->len; + *type = entry->type; + return 0; +} \ No newline at end of file diff --git a/src/kernel/include/memory.h b/src/kernel/include/memory.h index 5de76a9..2a73ca2 100644 --- a/src/kernel/include/memory.h +++ b/src/kernel/include/memory.h @@ -9,6 +9,8 @@ #include #define V2P(a) ((uintptr_t)(a) &~KERNEL_OFFSET) #define P2V(a) ((void *)((uintptr_t)(a) | KERNEL_OFFSET)) + +#define incptr(p, n) ((void *)(((uintptr_t)(p)) + (n))) #endif diff --git a/src/kernel/include/multiboot.h b/src/kernel/include/multiboot.h index 9964bd1..00f2a96 100644 --- a/src/kernel/include/multiboot.h +++ b/src/kernel/include/multiboot.h @@ -5,3 +5,25 @@ #define MBOOT2_ARCH 0 #define MBOOT2_LENGTH (Multiboot2HeaderEnd - Multiboot2Header) #define MBOOT2_CHECKSUM -(MBOOT2_MAGIC + MBOOT2_ARCH + MBOOT2_LENGTH) + +#define MBOOT2_TAG_CMDLINE 1 +#define MBOOT2_TAG_BOOTLOADER 2 +#define MBOOT2_TAG_MMAP 6 +#define MBOOT2_TAG_FBINFO 8 + +#ifndef __ASSEMBLER__ +#include +struct kernel_boot_data_st{ + int multiboot_version; + char *bootloader; + char *commandline; + size_t mmap_size; + unsigned int mmap_len; + void *mmap; +}; + +extern struct kernel_boot_data_st kernel_boot_data; + +int multiboot_init(uint64_t magic, void *mboot_info); +int multiboot_get_memory_ara(size_t index, uintptr_t *start, uintptr_t *end, uint32_t *type); +#endif \ No newline at end of file