Files
nub-os/src/arch/x86_64/boot/boot.asm
2025-09-06 20:22:51 +02:00

168 lines
3.6 KiB
NASM

global _start
global pml4
extern x86_64_main
extern kernel_end
%define FLAGS 0b10
%define MAGIC 0x1BADB002
%define CHECKSUM -(MAGIC + FLAGS)
section .multiboot
align 4
dd MAGIC
dd FLAGS
dd CHECKSUM
section .bss
align 16
resb 32768
stack_top:
section .bss
align 4096
pml4:
resb 4096
pdpt:
resb 4096
pd:
resb 4096
section .data
align 8
gdt64:
dq 0x0000000000000000
.code:
dq 0x00AF9A000000FFFF
.descriptor:
dw .end - gdt64 - 1
dq gdt64
.end:
section .data
align 8
multiboot_info:
dd 0
multiboot_magic:
dd 0
kernel_page_count:
dd 0
section .text
bits 32
_start:
mov esp, stack_top
; Save multiboot info pointer for later
mov [multiboot_magic], eax
mov [multiboot_info], ebx
; Check if cpuid is available by flipping bit 21
; in the eflags register and checking if the cpu flipped it back
pushfd
pop eax
mov ecx, eax
xor eax, 1 << 21
push eax
popfd
pushfd
pop eax
; If cpuid is available, eax should be different than ecx
xor eax, ecx
jz error
; Finally restore eflags register to the original value
push ecx
popfd
; Check if extended cpuid is available by calling cpuid with 0x80000000,
; If cpuid is available, eax will be greater than 0x80000000 after the call
mov eax, 0x80000000
cpuid
cmp eax, 0x80000001
jb error
; Check if long mode is available by calling cpuid with 0x80000001
; this will place the extended features of the cpu in edx
; Bit 29 tells us if long mode is supported or not
mov eax, 0x80000001
cpuid
test edx, 1 << 29
jz error
; Enable PAE by setting bit 5 in cr4 to 1
mov eax, cr4
or eax, 1 << 5
mov cr4, eax
; pml4[0] -> pdpt
mov eax, pdpt
or eax, 0x03
mov [pml4], eax
; pdpt[0] -> pd
mov eax, pd
or eax, 0x03
mov [pdpt], eax
; Calculate how many 2mb pages we need to identity map
mov ecx, kernel_end
add ecx, 0x1FFFFF ; Page align end of kernel
shr ecx, 21 ; ecx now holds the required pages
; Save the page count so we can pass it to c later
mov [kernel_page_count], ecx
; Identity map the 0x0 to kernel_end
mov edi, pd
mov eax, 0x83
.setup_pd:
mov [edi], eax
add eax, 0x200000
add edi, 8
loop .setup_pd
; Tell the cpu where pml4 is
mov eax, pml4
mov cr3, eax
lgdt [gdt64.descriptor]
; Enable long mode by setting bit 8 to 1 in EFER (Extended Feature Enable Register)
mov ecx, 0xc0000080
rdmsr
or eax, 1 << 8
wrmsr
; Enable paging by setting bit 31 in cr0 to 1
mov eax, cr0
or eax, 1 << 31
mov cr0, eax
jmp 0x8:long_mode
error:
cli
mov byte [0xb8000], 'E'
mov byte [0xb8002], 'R'
mov byte [0xb8004], 'R'
.hang:
hlt
jmp .hang
section .text
bits 64
long_mode:
; Clear segment registers in long mode
xor ax, ax
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
; Finally, we call in to c
mov edi, [multiboot_magic]
mov esi, [multiboot_info]
mov edx, [kernel_page_count]
call x86_64_main
.hang:
hlt
jmp .hang