Last active
May 1, 2021 21:22
-
-
Save hibariya/9dc9b836e39a04300a410e92368dec7d to your computer and use it in GitHub Desktop.
Revisions
-
hibariya revised this gist
Aug 14, 2016 . 2 changed files with 60 additions and 84 deletions.There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -7,4 +7,4 @@ clean: rm -rf *.bin run: bootable.bin qemu-system-x86_64 -monitor stdio bootable.bin This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -1,121 +1,97 @@ bits 16 org 0x7c00 k16bits: %define PML4T 0x8000 %define PDPT 0x9000 %define PDT 0xa000 %define PT 0xb000 cli ; Set up PML4T mov dword eax, PDPT or dword eax, 011b ; user-mode / R/W / PML4E present mov dword [PML4T], eax mov dword [PML4T + 4], 0 ; Set up PDPT mov dword eax, PDT or dword eax, 011b mov dword [PDPT], eax mov dword [PDPT + 4], 0 ; Set up PDT mov dword eax, PT or dword eax, 0011b mov dword [PDT], eax mov dword [PDT + 4], 0 ; Set up PT mov edi, PT mov ebx, 011b mov ecx, 512 create_pages: mov dword [edi], ebx mov dword [edi + 4], 0 add ebx, 0x1000 add edi, 8 loop create_pages ; Set CR4.PAE to 1 to enable 64-bit paging mov eax, cr4 or eax, 1 << 5 mov cr4, eax ; CR3 = PML4T mov eax, PML4T mov cr3, eax ; Enable 64-bit mode ; A logical processor uses IA-32e paging if CR0.PG = 1, CR4.PAE = 1, and IA32_EFER.LME = 1. (intel manual: Vol.3A 4.5 IA-32E PAGING) mov ecx, 0xc0000080 ; It's the argument for rdmsr following / MSR number of EFER is this constant rdmsr ; Read EFER into eax or eax, 1 << 8 ; Set EFER.LME (Long Mode Enable) to 1 wrmsr ; Set CR0.PE and CR0.PG to 1 to enable protected-mode and paging mov eax, cr0 or eax, 1 << 31 | 1 << 0 mov cr0, eax lgdt [GDT64.Pointer] jmp GDT64.Code:k64bits bits 64 k64bits: mov rax, 0x123 hlt GDT64: ; Global Descriptor Table (64-bit). .Null: equ $ - GDT64 ; The null descriptor. dw 0 ; Limit (low). dw 0 ; Base (low). db 0 ; Base (middle) db 0 ; Access. db 0 ; Granularity. db 0 ; Base (high). .Code: equ $ - GDT64 ; The code descriptor. dw 0 ; Limit (low). dw 0 ; Base (low). db 0 ; Base (middle) db 10011010b ; Access (exec/read). db 00100000b ; Granularity. db 0 ; Base (high). .Data: equ $ - GDT64 ; The data descriptor. dw 0 ; Limit (low). dw 0 ; Base (low). db 0 ; Base (middle) db 10010010b ; Access (read/write). db 00000000b ; Granularity. db 0 ; Base (high). .Pointer: ; The GDT-pointer. dw $ - GDT64 - 1 ; Limit. dq GDT64 ; Base. times 512 - 2 - ($ - $$) db 0 ; zero-pad the 512-byte sector to the last 2 bytes dw 0xaa55 ; Magic "boot signature" -
hibariya created this gist
Aug 3, 2016 .There are no files selected for viewing
This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,10 @@ all: bootable.bin bootable.bin: nasm boot.s -o $@ clean: rm -rf *.bin run: bootable.bin qemu-system-x86_64 -monitor stdio bootable.bin This file contains hidden or 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 charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,121 @@ ; http://davidad.github.io/blog/2014/02/18/kernel-from-scratch/ ; http://wiki.osdev.org/Setting_Up_Long_Mode#Setting_up_the_Paging bits 16 org 0x7c00 k16bits: ; The cli instruction disables maskable external interrupts. cli ; Set CR0.PE to 1 to enable 32-bit mode (al == eax) ; (Control register: https://en.wikipedia.org/wiki/Control_register) mov eax, cr0 or al, 1 mov cr0, eax jmp 0x08:k32bits bits 32 k32bits: ; Set up paging for 64-bit mode %define PML4E_ADDR 0x8000 %define PDPTE_ADDR 0x9000 %define PDE_ADDR 0xa000 %define PTE_ADDR 0xb000 %define PT_ADDR 0xc000 ; Disable paging in advance mov eax, cr0 and eax, 01111111111111111111111111111111b mov cr0, eax ; Set up PML4E mov dword eax, PDPTE_ADDR ; PDPTE_ADDR is the 1st entry of PML4E or dword eax, 011b ; user-mode / R/W / PML4E present mov dword [PML4E_ADDR], eax ; PML4E[0] = eax mov dword [PML4E_ADDR + 4], 0 ; Although we're in 32-bit mode, the table entry is 64 bits. We can just zero out the upper bits in this case. ; Set up PDPTE mov dword eax, PDE_ADDR or dword eax, 011b mov dword [PDPTE_ADDR], eax mov dword [PDPTE_ADDR + 4], 0 ; Set up PDE mov dword eax, PTE_ADDR or dword eax, 011b mov dword [PDE_ADDR], eax mov dword [PDE_ADDR + 4], 0 ; Set up PTE mov dword [PTE_ADDR], 011b mov dword [PTE_ADDR + 4], 0 ; Set up pages mov edi, PT_ADDR mov ebx, 011b mov ecx, 512 create_pages: mov dword [edi], ebx add ebx, 0x1000 add edi, 8 loop create_pages ; Set each CR4.PGE and CR4.PAE to 1 to enable 64-bit paging and global pages mov eax, 10100000b mov cr4, eax ; CR3 = PML4E_ADDR mov eax, PML4E_ADDR mov cr3, eax ; Enable 64-bit mode ; A logical processor uses IA-32e paging if CR0.PG = 1, CR4.PAE = 1, and IA32_EFER.LME = 1. (intel manual: Vol.3A 4.5 IA-32E PAGING) mov ecx, 0xc0000080 ; It's the argument for rdmsr following / MSR number of EFER is this constant rdmsr ; Read EFER into eax or eax, 100000000b ; Set EFER.LME (Long Mode Enable) to 1 wrmsr ; Set CR0.PG to 1 to enable paging mov eax, cr0 or eax, 0x80000000 mov cr0, eax ; Load Global Descriptor Table lgdt [gdt_hdr] jmp 0x08:k64bits bits 64 k64bits: mov rax, 0xdeadbeef hlt ; Grobal descriptor table entry ; https://en.wikipedia.org/wiki/Global_Descriptor_Table ; http://wiki.osdev.org/Global_Descriptor_Table %macro GDT_ENTRY 4 ; GDT_ENTRY(Base, Limit, Ring, Access) dw %2 & 0xffff ; Limit 0:15 dw %1 & 0xffff ; Base 0:15 db (%1 >> 16) & 0xff ; Base 16:23 db %4 | ((%3 << 4) & 0xf0) ; Access | (Ring << 4 & 0xf0) db (%3 & 0xf0) | ((%2 >> 16) & 0x0f) ; Flags (Ring & 0xf0) | Limit 16:19 db %1 >> 24 ; Base 24:31 %endmacro ; (Executable, Direction/Conforming, RW, Accessed) %define EXECUTE_READ 1010b %define READ_WRITE 0010b ; (Granularity, Size, ?, 0), (Present, Privilege(2), 1) %define RING0 10101001b gdt_hdr: dw gdt_end - gdt - 1 dd gdt gdt: GDT_ENTRY 0, 0, 0, 0 GDT_ENTRY 0, 0xffffff, RING0, EXECUTE_READ GDT_ENTRY 0, 0xffffff, RING0, READ_WRITE gdt_end: times 512 - 2 - ($ - $$) db 0 ; zero-pad the 512-byte sector to the last 2 bytes dw 0xaa55 ; Magic "boot signature"