Skip to content

Instantly share code, notes, and snippets.

@chop0
Created November 17, 2023 08:55
Show Gist options
  • Save chop0/a52a775993e8da7176e8fec6be4f5874 to your computer and use it in GitHub Desktop.
Save chop0/a52a775993e8da7176e8fec6be4f5874 to your computer and use it in GitHub Desktop.
ASM bootloader that sets up long mode paging with a self-referential PML4E
[bits 16]
load:
mov ah, 0x02 ; read disk sectors
mov al, 0x01 ; 1 sector (probably should statically calculate this somehow, or use linker script)
mov ch, 0x00 ; track
mov cl, 0x02 ; sector
mov dh, 0x00; head
; mov dl, 0x00
mov bx, 0
mov es, bx
mov bx, 0
.readsector:
int 0x13
jc .readsector ; try again if it fails
jmp _start
; -- real mode --
_start:
lea esp, [__stack_top]
mov eax, cr0
or eax, 1 << 0
mov cr0, eax
lgdt [GDT32.Pointer]
jmp GDT32.Code:protected_mode_entry
; -- protected mode w/ segmentation --
[bits 32]
protected_mode_entry:
mov edi, 0x3000
mov cr3, edi
xor eax, eax
mov ecx, 4096
rep stosd
mov eax, cr3
mov dword [eax], 0x4000 | 3
add eax, 4096
mov dword [eax], 0x5000 | 3
add eax, 4096
mov dword [eax], 0x6000 | 3
add eax, 4096
mov ebx, 0x00000003
mov ecx, 512
set_page_entry:
mov dword [eax], ebx
add eax, 8
add ebx, 0x1000
loop set_page_entry
mov ecx, 0xC0000080
rdmsr
or eax, 1 << 8 ; efer.lme
wrmsr
mov edi, cr4
or edi, 1 << 5 ; PAE
mov cr4, edi
mov edi, cr0
or edi, 1 << 31 ; paging on
mov cr0, edi
lgdt [GDT64.Pointer]
jmp GDT64.Code:long_mode_entry
[bits 64]
long_mode_entry:
mov rbp, rsp
xor r8, r8
rdtsc
and eax, 0xff
mov r8, rax
nop
shl r8, 9
mov qword [0x3000 + 8*eax], 0x8000 | 0x3 ; pml4e
rdtsc
and eax, 0x1ff
or r8, rax
shl r8, 9
mov qword [0x8000 + 8*eax], 0x8000 | 0x3 ; pdpte
rdtsc
and eax, 0x1ff
or r8, rax
shl r8, 9
mov qword [0x8000 + 8*eax], 0x9000 | 0x3 ; pde
mov qword [0x9000], 0x0 | 0x3
shl r8, 12
lea r14, [r8 + add_self_refential_mapping]
jmp r14
add_self_refential_mapping:
rdtsc
and eax, 0x1ff ; meagre 9 bits of entropy
cmp eax, 0
je add_self_refential_mapping
mov qword [0x3000 + 8*eax], 0x3000 | 0x3 ; pml4e
mov qword [0x3000], 0x0
cli
.done:
hlt
GDT64:
dq 0
.Code: equ $ - GDT64
dq (1<<44) | (1<<47) | (1<<41) | (1<<43) | (1<<53)
.Data: equ $ - GDT64
dq (1<<44) | (1<<47) | (1<<41)
.Pointer:
dw .Pointer - GDT64 - 1
dq GDT64
GDT32:
.Null: equ $ - GDT32
dd 0x0, 0x0
.Code: equ $ - GDT32
dw 0xffff, 0x0
db 0x0, 10011010b, 11001111b, 0x0
.Pointer:
dw $ - GDT32 - 1
dd GDT32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment