Created
November 17, 2023 08:55
-
-
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
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
[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