2023-04-19 04:17:11 +03:00

153 lines
2.6 KiB
NASM

; https://wiki.osdev.org/Creating_a_64-bit_kernel
; https://wiki.osdev.org/Entering_Long_Mode_Directly
KERNEL_VIRTUAL_BASE equ 0xFFFFFFFF80000000 ; 512GB
KERNEL_LMA equ 0x1000000 ; 16MB
KERNEL_STACK_SIZE equ 0x4000 ; 16KB
extern Multiboot2Entry
extern BootPageTable
extern UpdatePageTable
extern UpdatePageTable64
extern DetectCPUID
extern Detect64Bit
extern LoadGDT32
global MB2_start
extern MB2_start_c
[bits 32]
section .bootstrap.data
global MB2_HeaderMagic
MB2_HeaderMagic:
times (0x64) dq 0
global MB2_HeaderInfo
MB2_HeaderInfo:
times (0x64) dq 0
section .bootstrap.text
MB2_start:
cli
; mov word [0xb8F00], 0x072E ; .
mov [MB2_HeaderMagic], eax
mov [MB2_HeaderInfo], ebx
; We need to check if the CPU supports 64-bit mode
call DetectCPUID
call Detect64Bit
; mov word [0xb8F02], 0x072E ; .
mov ecx, cr0
and ecx, 0x7fffffff ; Clear PG
mov cr0, ecx
mov ecx, cr4
or ecx, 0x10 ; Set PSE
or ecx, 0x20 ; Set PAE
mov cr4, ecx
; Load the GDT and update the page table
call LoadGDT32
call UpdatePageTable
; Load the new page table
mov edi, BootPageTable
mov cr3, edi
; mov word [0xb8F04], 0x072E ; .
; Enable long mode
mov ecx, 0xC0000080 ; EFER
rdmsr
or eax, 0x800 | 0x100 | 0x1 ; Set LME, LMA, SCE
wrmsr
mov ecx, cr0
or ecx, (0x80000000 | 0x1) ; Set PG and PE
mov cr0, ecx
lgdt [GDT64.Ptr]
; xor eax, eax
; sgdt [eax]
; test eax, eax
; jz .InvalidGDT
; .InvalidGDT:
; mov word [0xb8F07], 0x4 ; Red
; hlt
jmp GDT64.code:HigherHalfStart
[bits 64]
HigherHalfStart:
cli
; mov word [0xb8F06], 0x072E ; .
call UpdatePageTable64
; Load the new page table
mov rdi, BootPageTable
mov cr3, rdi
mov ax, GDT64.data
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
; mov word [0xb8F08], 0x072E ; .
mov rsp, (KernelStack + KERNEL_STACK_SIZE)
mov rbp, (KernelStack + KERNEL_STACK_SIZE)
cld
cli
call Multiboot2Entry
.Loop:
hlt
jmp .Loop
section .bootstrap.bss
align 16
KernelStack:
resb KERNEL_STACK_SIZE
; Access bits
PRESENT equ 1 << 7
NOT_SYS equ 1 << 4
EXEC equ 1 << 3
DC equ 1 << 2
RW equ 1 << 1
ACCESSED equ 1 << 0
; Flags bits
GRAN_4K equ 1 << 7
SZ_32 equ 1 << 6
LONG_MODE equ 1 << 5
section .bootstrap.data
GDT64:
.null: equ $ - GDT64
dq 0
.code: equ $ - GDT64
dd 0xFFFF
db 0
db PRESENT | NOT_SYS | EXEC | RW
db GRAN_4K | LONG_MODE | 0xF
db 0
.data: equ $ - GDT64
dd 0xFFFF
db 0
db PRESENT | NOT_SYS | RW
db GRAN_4K | SZ_32 | 0xF
db 0
.tss: equ $ - GDT64
dd 0x00000068
dd 0x00CF8900
.Ptr:
dw $ - GDT64 - 1
dq GDT64