asm { start: ;; Copy Kernel to 1 MB cld ; Copy forward mov esi, 0h40000 mov edi, 0h100000 mov ecx, 512 / 4 ; How many 4 bytes, right now 512 because kernel has 1 sector rep_movsd ; Check longmode support mov eax, 0h80000000 cpuid cmp eax, 0h80000001 ; This is like jb jc &lmns mov eax, 0h80000001 cpuid test edx, 0h20000000 jz &lmns ;; Disable Paging ; mov eax, cr0 du8 0h0F du8 0h20 du8 0hC0 and eax, 0h7FFFFFFE ; mov cr0, eax du8 0h0F du8 0h22 du8 0hC0 ;; Clearing the tables mov edi, 0h30000 ; PML4_ADDRESS xor eax, eax mov ecx, 4096 / 4 rep_stosd mov edi, 0h31000 ; PDPT ADDRESS xor eax, eax mov ecx, 4096 / 4 rep_stosd mov edi, 0h32000 ; PDT ADDRESS xor eax, eax mov ecx, 4096 / 4 rep_stosd mov edi, 0h30000 ; mov cr3, edi du8 0h0F du8 0h22 du8 0hDF ;; Filling the tables ; mov [edi], PDPT_ADDRESS | ADDRESS_MAS | READABLE | PRESENT du8 0hC7 du8 0h07 du32 0h31000 | 1 | 2 ; mov edi, PDPT_ADDRESS mov edi, 0h31000 ; mov [edi], PDT_ADDRESS | ADDRESS_MASK | READABLE | PRESENT du8 0hC7 du8 0h07 du32 0h32000 | 1 | 2 ; mov edi, PDT_ADDRESS mov edi, 0h32000 ; mov ebx, READABLE | PRESENT | HUGE mov ebx, 1 | 2 | 0h80 mov ecx, 512 page_loop: ; mov [edi], ebx du8 0h89 du8 0h1F add ebx, 0h200000 ; 2 MB add edi, 8 dec ecx jnz &page_loop lmphase: ;; Setup PAE ; mov eax, cr4 du8 0h0F du8 0h20 du8 0hE0 or eax, 0h20 ; mov cr4, eax du8 0h0F du8 0h22 du8 0hE0 ;; Setup LM bit mov ecx, 0hC0000080 rdmsr or eax, 0h100 wrmsr ;; Enable Paging ; mov eax, cr0 du8 0h0F du8 0h20 du8 0hC0 or eax, 0h80000000 | 1 ; mov cr0, eax du8 0h0F du8 0h22 du8 0hC0 ; lgdt [GDT_DESC] 16 & 32 du8 0h0F du8 0h01 du8 0h15 du32 GDT_DESC ; jmp CODE_DESC:lmjump du8 0hEA du32 lmjump du16 GDT_CODE - GDT_START lmjump: ; mov ax, DATA_DESC du8 0hC7 du8 0hC0 du32 GDT_DATA - GDT_START ; mov ds, ax du8 0h8E du8 0hD8 ; mov es, ax du8 0h8E du8 0hC0 ; mov fs, ax du8 0h8E du8 0hE0 ; mov gs, ax du8 0h8E du8 0hE8 ; mov ss, ax du8 0h8E du8 0hD0 mov rsp, 0h90000 mov rax, 0h100000 jmp rax hlt } asm { lmns: mov esi, lmnsmsg jmp &pmtorm } asm { ;; Drop to RealMode after an error occurs and output the message ;; stored at the address pointed by the si/esi/rsi register. pmtorm: cli ; lgdt [RGDT_DESC] du8 0h0F du8 0h01 du8 0h15 du32 RGDT_DESC ; jmp (RGDT_CODE - RGDT_START):pmode16 du8 0hEA du32 pmode16 du16 RGDT_CODE - RGDT_START pmode16: ; mov ax, RGDT_DATA - RGDT_START du8 0hB8 du16 RGDT_DATA - RGDT_START ; mov ds, ax du8 0h8E du8 0hD8 ; mov es, ax du8 0h8E du8 0hC0 ; mov fs, ax du8 0h8E du8 0hE0 ; mov gs, ax du8 0h8E du8 0hE8 ; mov ss, ax du8 0h8E du8 0hD0 ;; Disable Paging ; mov eax, cr0 du8 0h0F du8 0h20 du8 0hC0 du8 0h66 and eax, 0h7FFFFFFE ; mov cr0, eax du8 0h0F du8 0h22 du8 0hC0 ; jmp 0:rmode du8 0hEA du16 rmode du16 0 rmode: ; xor ax, ax du8 0h31 du8 0hC0 ; mov ds, ax du8 0h8E du8 0hD8 ; mov es, ax du8 0h8E du8 0hC0 ; mov fs, ax du8 0h8E du8 0hE0 ; mov gs, ax du8 0h8E du8 0hE8 ; mov ss, ax du8 0h8E du8 0hD0 ; mov sp, 0h7c00 du8 0hBC du16 0h7c00 ; lidt [RIDT_DESC] du8 0h0F du8 0h01 du8 0h1E du32 RIDT_DESC sti mov ah, 0h0e print_loop: ; mov al, [si] du8 0h8A du8 0h04 cmp al, 0h00 ; jz &print_done du8 0h0F du8 0h84 du16 &print_done int 0h10 ; inc si du8 0hFF du8 0hC6 ; jmp print_loop du8 0hE9 du16 &print_loop print_done: ; jmp $ du8 0hE9 du16 0hFFFD } asm { GDT_START: du64 0 ; Null GDT_CODE: du16 0hFFFF du16 0 du8 0 du8 0h9A du8 0hAF du8 9 GDT_DATA: du16 0hFFFF du16 0 du8 0 du8 0h92 du8 0hCF du8 0 GDT_END: GDT_DESC: du16 GDT_END - GDT_START - 1 du64 GDT_START } asm { RGDT_START: du64 0 ; Null RGDT_CODE: du16 0hFFFF du16 0 du8 0 du8 0h9A du8 0 du8 0 RGDT_DATA: du16 0hFFFF du16 0 du8 0 du8 0h92 du8 0 du8 0 RGDT_END: RGDT_DESC: du16 RGDT_END - RGDT_START - 1 du32 RGDT_START RIDT_DESC: du16 0h3FF du32 0 } asm { lmnsmsg: du8 "Boot failed! Long mode not supported!", 13, 10, 0 }