Created
September 2, 2013 02:32
-
-
Save erincandescent/6408764 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "mbconstants.h" | |
#include "architecture.h" | |
.extern KMain | |
.extern BootStackTop | |
.extern IMAGE_END | |
.extern BSS_END | |
#define MB2_FLAGS (MB2_IFLAG_VIDEO | MB2_IFLAG_MBFIELDS) | |
#define MB2_CHECKSUM ((-(MB2_IMAGE_MAGIC + MB2_FLAGS)) & 0xFFFFFFFF) | |
// ------------------------------------------------------------ | |
// The following are all physical addresses! | |
// ------------------------------------------------------------ | |
# Multiboot Header | |
.code32 | |
.align 8 | |
mb_hdr: | |
# Primary header | |
.long MB2_IMAGE_MAGIC | |
.long MB2_FLAGS | |
.long MB2_CHECKSUM | |
# Address header | |
.long mb_hdr - VIRTUAL_BASE | |
.long 0x00100000 | |
.long IMAGE_END - VIRTUAL_BASE | |
.long BSS_END - VIRTUAL_BASE | |
.long KLoader - VIRTUAL_BASE | |
# Video mode | |
.long 1 # EGA Text mode | |
.long 80 # 80 char wide | |
.long 50 # 50 char tall | |
.long 0 # Bits per pixel (ignored) | |
.global KLoader | |
KLoader: | |
# Switch to our GDT | |
lgdt GDTR32 - VIRTUAL_BASE | |
# Store away Multiboot info | |
movl %eax, %edi # di and si are sufficiently far away to not be used. More importantly, | |
movl %ebx, %esi # %rdi and %rsi are the first and second function params in the ABI | |
# Check CPU does long mode | |
movl $0x80000000, %eax | |
cpuid | |
cmpl $0x80000000, %eax | |
jbe noLong | |
movl $0x80000001, %eax | |
cpuid | |
bt $29, %edx | |
jnc noLong | |
# Enable PAE | |
movl %cr4, %eax | |
bts $5, %eax | |
movl %eax, %cr4 | |
# Load page table address | |
movl $(KPML4Base - VIRTUAL_BASE), %eax | |
movl %eax, %cr3 | |
# Set LME | |
mov $0xC0000080, %ecx | |
rdmsr | |
bts $8, %eax | |
wrmsr | |
# Enable paging | |
mov %cr0, %eax | |
bts $31, %eax | |
mov %eax, %cr0 | |
# Now in long-compatibility32 mode | |
# Jump to 64-bit code | |
ljmp $0x18, $(KStub64 - VIRTUAL_BASE) | |
.code64 | |
KStub64: | |
movabs $KEntry64, %rax | |
jmp *%rax | |
.code32 | |
noLong: | |
mov $0xb8000, %eax | |
mov $nlmsg - VIRTUAL_BASE, %ebx | |
mov $0x40, %cl | |
0: mov (%ebx), %ch | |
test $0xff, %cl | |
jz 1f | |
mov %cx, (%eax) | |
inc %ebx | |
add $2, %eax | |
jmp 0b | |
1: jmp 1b | |
nlmsg: | |
.asciz "64-bit processor required" | |
GDTR32: | |
.word 0xFFFF | |
.long KGDT - VIRTUAL_BASE | |
// ------------------------------------------------------------ | |
// Virtual addresses from now on! | |
// ------------------------------------------------------------ | |
.code64 | |
KEntry64: | |
# Reload GDT | |
leaq GDTR(%rip), %rax | |
lgdt (%rax) | |
mov $0x10, %ax | |
mov %ax, %ds | |
mov %ax, %es | |
mov %ax, %ss | |
# Load stack | |
leaq BootStackTop(%rip), %rsp | |
# Finished | |
call KMain | |
# KMain returned? | |
movq $(VIRTUAL_BASE + 0xB8000), %rax | |
lea remsg(%rip), %rbx | |
mov $0x0F, %ch | |
0: mov (%rbx), %cl | |
test $0xff, %cl | |
jz 1f | |
mov %cx, (%rax) | |
inc %rbx | |
add $2, %rax | |
jmp 0b | |
1: jmp 1b | |
remsg: | |
.asciz "Kernel returned from main (fault)" | |
.section .data | |
.global GDTR | |
GDTR: | |
.word 0xFFFF | |
.quad KGDT | |
.align 8 | |
.global KGDT | |
KGDT: | |
# Segment 0x00: Required NULL | |
.quad 0 | |
# Segment 0x08: Code32 | |
.word 0xFFFF # 4GB limit[0..15] | |
.word 0 # 0 Base[0..15] | |
.byte 0 # 0 Base[16..23] | |
.byte 0x9A # Present, Code, Readable, Ring 0 | |
.byte 0xCF # 4GB limit[16..20], 4kb granularity, 32bit size | |
.byte 0x00 # 0 Base [24..31] | |
# Segment 0x10: Data32 | |
.word 0xFFFF # 4GB limit[0..15] | |
.word 0 # 0 Base[0..15] | |
.byte 0 # 0 Base[16..23] | |
.byte 0x93 # Present, Data, Writable, Ring 0 | |
.byte 0xCF # 4GB limit[16..20], 4kb granularity, 32bit size | |
.byte 0x00 # 0 Base [24..31] | |
# Segment 0x18: Code64 | |
.word 0 # Limit ign | |
.word 0 # Base ign | |
.byte 0 # Base ign | |
.byte 0x9A # Present, Code, Readable, Ring 0 | |
.byte 0xA0 # 4kb granularity, long mode | |
.byte 0 # Base ign | |
# Zero rest | |
.fill 8188, 8, 0 | |
.align 4096 | |
.global KPML4Base | |
KPML4Base: | |
# Identity map start | |
.quad 0x103 + (PDPTBase - VIRTUAL_BASE) | |
.fill 255, 8, 0 | |
# Map kernel | |
.quad 0x103 + (PDPTBase - VIRTUAL_BASE) | |
.fill 255, 8, 0 | |
# Point to PD for first 1GB | |
PDPTBase: | |
.quad 0x103 + (PDBase - VIRTUAL_BASE) | |
.fill 511, 8, 0 | |
# Identity map first 1GB (We don't know if the CPU | |
# supports 1GB pages) | |
PDBase: | |
.set paddr, 0 | |
.rept 512 | |
.quad paddr | 0x183 | |
.set paddr, paddr + 0x0200000 | |
.endr | |
.section .bss | |
.align 8 | |
BootStack: | |
.space 0x10000, 0 | |
BootStackTop: |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment