[BOOT] Multiboot compliant kernel which runs 64 bit code

This commit is contained in:
2016-07-24 00:45:20 +02:00
parent 1f8d5b3482
commit df86be2973
13 changed files with 433 additions and 4 deletions

122
kernel/boot/boot.S Normal file
View File

@@ -0,0 +1,122 @@
.intel_syntax noprefix
#include <mem.h>
// Some info from here: http://os.phil-opp.com/multiboot-kernel.html
.section .text
.global _start
.code32 // GRUB leaves us in 32 bit mode
_start:
cli
// Check if long mode is available
// Otherwise, there's no point in continuing
call check_longmode
// Enable long mode through process described in
// AMD64 manual vol. 2 ch. 14
// Enable Physical Address Extension
mov eax, cr4
or eax, 1<<5
mov cr4, eax
// Load page directory into cr3
mov eax, offset V2P(BootP4)
mov cr3, eax
// Enable long mode
mov ecx, 0xC0000080
rdmsr
or eax, 1<<8
wrmsr
// Enable paging
mov eax, cr0
or eax, 1<<31
mov cr0, eax
// We are now in 32 bit long mode
// Go to 64 bit mode by loading a GDT
// and perforing a far jump
lgdt [V2P(BootGDTp)]
mov eax, 0x10
mov ss, eax
mov ds, eax
mov es, eax
.extern long_mode_start
jmp 0x8:V2P(long_mode_start)
.code64
long_mode_start:
// We are now in 64 bit long mode
// but we are still running code in the identity mapped low memory kernel mirror
// Next we jump to code in high memory (> 32 bits)
movabs rax, offset .upper_memory
jmp rax
.upper_memory:
// We are now in high memory
// Set up a stack and set up a fake return address to stop backtracing
movabs rsp, offset BootStack
push 0
mov rbp, rsp
// Remove identity mapping
mov rax, 0x0
mov [V2P(BootP4)], rax
// Call c kernel code
.extern kmain
call kmain
hlt
.code32
// Check if CPUID is available
// Method described in AMD64 manual vol. 3
check_cpuid:
pushfd
pushfd
xor dword ptr[esp], 0x00200000
popfd
pushfd
pop eax
xor eax, [esp]
popfd
and eax, 1<<21
jz error
ret
// Check if long mode is available using cpuid
// AMD manual vol. 3 Appendix E
check_longmode:
call check_cpuid
mov eax, 0x80000000
cpuid
cmp eax, 0x80000001
jb error
mov eax, 0x80000001
cpuid
test edx, 1<<29
jz error
ret
// Jump here if something went wrong
error:
// Print ERR! to screen
mov [0xb8000], dword ptr 0x4f524f45
mov [0xb8004], dword ptr 0x4f214f52
jmp .

View File

@@ -0,0 +1,54 @@
.intel_syntax noprefix
#include <mem.h>
#include <gdt.h>
// Hardcode the initial page mapping
// Identity map the first GiB of memory
// Also map the same memory at KERNEL_OFFSET
.section .data
.align 0x1000
.global BootP4
BootP4:
.quad V2P(BootP3) + (PAGE_PRESENT | PAGE_WRITE)
.rept P4_OFFSET(KERNEL_OFFSET)-1
.quad 0x0
.endr
.quad V2P(BootP3) + (PAGE_PRESENT | PAGE_WRITE)
.rept 510 - P4_OFFSET(KERNEL_OFFSET) + 1
.quad 0x0
.endr
BootP3:
.quad V2P(BootP2) + (PAGE_PRESENT | PAGE_WRITE)
.rept 511
.quad 0x0
.endr
BootP2:
.set i, 0
.rept 512
.quad (i << 21) + (PAGE_PRESENT | PAGE_WRITE | PAGE_HUGE)
.set i, (i+1)
.endr
// Hardcode initial GDT segments
// Only kernel code (0x8) and data (0x10) for now
.section .rodata
.align 0x1000
.global BootGDT
.global BootGDTp
BootGDT:
.quad 0
.quad (GDT_PRESENT | GDT_CODEDATA | GDT_WRITE | GDT_EXECUTE | GDT_64BIT)
.quad (GDT_PRESENT | GDT_CODEDATA | GDT_WRITE)
BootGDTp: // We can't put the gdt pointer in the gdt, it's too big
.short 3*8-1
.quad V2P(BootGDT)
// Reserved space for the stack
.section .bss
.global BootStack
.align 0x1000
.skip 0x1000
BootStack:

34
kernel/boot/kmain.c Normal file
View File

@@ -0,0 +1,34 @@
#include <mem.h>
#define VGA_MEMORY 0xb8000
#define VGA_ROWS 24
#define VGA_COLS 80
void clear_screen()
{
// Clear the video memory
unsigned char *m = (void *)P2V(VGA_MEMORY);
for(int i = 0; i < VGA_ROWS*VGA_COLS*2; i++)
{
*m++ = 0;
}
}
void prints(const char *s, unsigned int row, unsigned int col)
{
// Very simple pure ascii string printing
unsigned char *m = (void *)P2V(VGA_MEMORY);
m += 2*VGA_COLS*row+2*col;
while(*s)
{
*m++ = *s++;
*m++ = 0x7;
}
}
int kmain(void)
{
clear_screen();
prints("Hello, world!", 0, 0);
for(;;)asm("hlt");
}

View File

@@ -0,0 +1,23 @@
.section .multiboot
#include <multiboot.h>
.align 0x1000
MultiBootHeader1:
.long MBOOT1_MAGIC
.long MBOOT1_HEADER_FLAGS
.long MBOOT1_HEADER_CHECKSUM
.align 0x1000
MultiBootHeader:
.long MBOOT2_MAGIC
.long MBOOT2_ARCH
.long MBOOT2_LENGTH
.long MBOOT2_CHECKSUM
// Multiboot tags
// End tag
.short 0
.short 0
.long 8
MultiBootHeaderEnd: