From bd7d4366b6643b5c6cd04f40dd32f5d9c9575fd6 Mon Sep 17 00:00:00 2001 From: Aleksa Vuckovic Date: Fri, 5 Aug 2022 14:33:51 +0200 Subject: organised files; switched to recursive make --- kernel/src/boot/boot.S | 181 +++++++++++++++++++++++++++++++++++++++++++ kernel/src/boot/boot64.S | 19 +++++ kernel/src/boot/header.S | 40 ++++++++++ kernel/src/boot/multiboot2.c | 41 ++++++++++ 4 files changed, 281 insertions(+) create mode 100644 kernel/src/boot/boot.S create mode 100644 kernel/src/boot/boot64.S create mode 100644 kernel/src/boot/header.S create mode 100644 kernel/src/boot/multiboot2.c (limited to 'kernel/src/boot') diff --git a/kernel/src/boot/boot.S b/kernel/src/boot/boot.S new file mode 100644 index 0000000..ee35eeb --- /dev/null +++ b/kernel/src/boot/boot.S @@ -0,0 +1,181 @@ +.global _start +.extern begin_long_mode + +.section .text +.code32 + +_start: + cli + mov $stack_top, %esp + pushl $0 + pushl %eax + pushl $0 + pushl %ebx + + call check_multiboot + call check_cpuid + call check_long_mode + + call setup_page_tables + call enable_paging + + lgdt gdt_pointer + ljmp $0x08, $begin_long_mode + + +check_multiboot: + cmp $0x36d76289, %eax + jne no_multiboot + + ret + +check_cpuid: + pushfl + pop %eax + mov %eax, %ecx + xor $1<<21, %eax + push %eax + popfl + pushfl + pop %eax + push %ecx + popfl + cmp %eax, %ecx + je no_cpuid + + ret + +check_long_mode: + mov $0x80000000, %eax + cpuid + cmp $0x80000001, %eax + jb no_long_mode + + mov $0x80000001, %eax + cpuid + test $1<<29, %edx + jz no_long_mode + + ret + +setup_page_tables: + mov $page_table_lvl3, %eax + or $0x3, %eax + mov %eax, page_table_lvl4 + + mov $page_table_lvl2, %eax + or $0x3, %eax + mov %eax, page_table_lvl3 + + mov $page_table_lvl2 + 4096, %eax + or $0x3, %eax + mov %eax, page_table_lvl3+8 + + mov $page_table_lvl2 + 8192, %eax + or $0x3, %eax + mov %eax, page_table_lvl3+16 + + mov $page_table_lvl2 + 12288, %eax + or $0x3, %eax + mov %eax, page_table_lvl3+24 + + + movl $0, %ecx +1: + movl $0x200000, %eax + mul %ecx + or $0b10000011, %eax + movl $page_table_lvl2, %edx + leal (%edx, %ecx, 8), %edx + movl %eax, (%edx) + inc %ecx + cmp $512*4, %ecx + jne 1b + + ret + +enable_paging: + // enable PAE + mov %cr4, %edx + or $1<<5 ,%edx + mov %edx, %cr4 + + // set LME (long mode enable) + mov $0xC0000080, %ecx + rdmsr + or $1<<8, %eax + wrmsr + + // page_table_lvl4 + mov $page_table_lvl4, %eax + mov %eax, %cr3 + + // enable paging (+ protected mode if not already enabled) + mov %cr0, %eax + or $1<<31 + 1<<0, %eax + mov %eax, %cr0 + + ret + +no_multiboot: + hlt + +no_cpuid: + hlt + +no_long_mode: + hlt + + +.section .bss +.align 4096 + +// stack +stack_bottom: + .skip 4096*4 +stack_top: + +// page tables +page_table_lvl4: + .skip 4096 +page_table_lvl3: + .skip 4096 +// map first 4GB +page_table_lvl2: + .skip 4096*4 + +// Access bits +.section .rodata +.set PRESENT, 1 << 7 +.set NOT_SYS, 1 << 4 +.set EXEC, 1 << 3 +.set DC, 1 << 2 +.set RW, 1 << 1 +.set ACCESSED, 1 << 0 + +// Flags bits +.set GRAN_4K, 1 << 7 +.set SZ_32, 1 << 6 +.set LONG_MODE, 1 << 5 + +gdt: +gdt_null = . - gdt + .quad 0 +gdt_code = . - gdt + .long 0xFFFF // Limit & Base (low, bits 0-15) + .byte 0 // Base (mid, bits 16-23) + .byte PRESENT | NOT_SYS | EXEC | RW // Access + .byte GRAN_4K | LONG_MODE | 0xF // Flags & Limit (high, bits 16-19) + .byte 0 // Base (high, bits 24-31) +gdt_data = . - gdt + .long 0xFFFF + .byte 0 + .byte PRESENT | NOT_SYS | RW + .byte GRAN_4K | SZ_32 | 0xF + .byte 0 +gdt_tss = . - gdt + .long 0x00000068 + .long 0x00CF8900 +gdt_pointer: + .word . - gdt - 1 + .quad gdt diff --git a/kernel/src/boot/boot64.S b/kernel/src/boot/boot64.S new file mode 100644 index 0000000..be87412 --- /dev/null +++ b/kernel/src/boot/boot64.S @@ -0,0 +1,19 @@ +.global begin_long_mode + +.section .text +.code64 + +begin_long_mode: + // reload segment registers + mov $0x10, %eax + mov %eax, %ss + mov %eax, %ds + mov %eax, %es + mov %eax, %fs + mov %eax, %gs + + popq %rdi + popq %rsi + + call kernel_main + hlt diff --git a/kernel/src/boot/header.S b/kernel/src/boot/header.S new file mode 100644 index 0000000..bbcb9be --- /dev/null +++ b/kernel/src/boot/header.S @@ -0,0 +1,40 @@ +// multiboot tags +.set TAG_END, 0 +.set TAG_FRAMEBUFFER, 5 + +// multiboot flags +.set TAG_REQUIRED, 0 +.set TAG_OPTIONAL, 1 + +# multiboot2 header constants +.set MAGIC, 0xe85250d6 +.set ARCH, 0 +.set HEADER_LENGTH, (header_end - header_start) +.set CHECKSUM, 0x100000000 - (MAGIC + ARCH + HEADER_LENGTH) + +.section .multiboot_header, "a" +.align 4 +header_start: + # magic + .align 8 + .long MAGIC + .long ARCH + .long HEADER_LENGTH + .long CHECKSUM + + # framebuffer + .align 8 + .word TAG_FRAMEBUFFER + .word TAG_REQUIRED + .long 20 + .long 1024 + .long 768 + .long 32 + + # end tag + .align 8 + .word TAG_END + .word TAG_REQUIRED + .long 8 + +header_end: diff --git a/kernel/src/boot/multiboot2.c b/kernel/src/boot/multiboot2.c new file mode 100644 index 0000000..e228ce1 --- /dev/null +++ b/kernel/src/boot/multiboot2.c @@ -0,0 +1,41 @@ +#include +#include +#include + +fb_t fb; + +/* https://www.gnu.org/software/grub/manual/multiboot2/html_node/Boot-information-format.html */ + +void init_fb(mb2_tag_header* multiboot_bootinfo, uint32_t multiboot_magic) +{ + if (multiboot_magic != MB2_MAGIC) { + // not loaded by multiboot2 bootloader + __asm__ volatile ("hlt;"); + } + + // we will store framebuffer information here + static mb2_tag_fb* tag_fb; + + // skip first 8 bytes (total_size + reserved) + mb2_tag_header* tag_header = multiboot_bootinfo + 1; + + while (tag_header->type != MB2_TAG_END) { + // process tag_type + switch(tag_header->type) { + case MB2_TAG_FB: + tag_fb = (mb2_tag_fb*)tag_header; + break; + default: + break; + } + + // next mb2_tag + tag_header += tag_header->size / 8 + ((tag_header->size % 8) > 0); + } + + fb.addr = tag_fb->framebuffer_addr; + fb.width = tag_fb->framebuffer_width; + fb.height = tag_fb->framebuffer_height; + fb.pitch = tag_fb->framebuffer_pitch; + fb.bpp = tag_fb->framebuffer_bpp; +} -- cgit v1.2.3