diff --git a/bootloader-legacy/boot.asm b/bootloader-legacy/boot.asm index 41043c6ae76886172467fcccf8a58bb74d36f625..ca3ea6ebff88b80ab2194e192aa3e55d97f99190 100644 --- a/bootloader-legacy/boot.asm +++ b/bootloader-legacy/boot.asm @@ -100,13 +100,42 @@ _prot_begin: mov ebx, _motd_32 call println_vga + ; Test if 64bit available + call test_support_long_mode + cmp eax, 0 + je _test_passed + mov ebx, _motd_no_long_mode + call println_vga + jmp _stall ; debug, tmp + jmp _call_kern_32 +_test_passed: + + jmp inline_enter_long_mode +%include "./inline_x64lib.inc" + jmp _call_kern_64 + +[bits 32] +_call_kern_32: ; Enter the kernel. This should never return. call KERN_ADDR ; Kernel returns. mov ebx, _motd_endk call println_vga + jmp _stall + +[bits 64] +_call_kern_64: + ; Enter the kernel. This should never return. + call KERN_ADDR + ; Kernel returns. + mov ebx, _motd_endk + call println_vga + jmp _stall + + +[bits 32] _stall: jmp $ @@ -118,6 +147,8 @@ _motd_kern_ok: db '[LOAD KERN SUCC]', 0x0 _motd_endk: db '[LOAD KERN SUCC] [ENTER X86 MODE SUCC] [KERN EXITED]', 0x0 +_motd_no_long_mode: + db '[ENTER LONG MODE ERR] NOT_SUPPORTED', 0x0 _boot_drive_id: db 0x0 diff --git a/bootloader-legacy/x64lib.inc b/bootloader-legacy/inline_x64lib.inc similarity index 65% rename from bootloader-legacy/x64lib.inc rename to bootloader-legacy/inline_x64lib.inc index 4193e86e9f8dd17adc90197c63246b4052b0f2f6..a34b39aa7946d7f4a76f9c2cabc2e2b4d361d045 100644 --- a/bootloader-legacy/x64lib.inc +++ b/bootloader-legacy/inline_x64lib.inc @@ -66,7 +66,33 @@ _fail_no_long_mode_3: ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -enter_long_mode: +GDT64: ; Global Descriptor Table (64-bit). + .Null: equ $ - GDT64 ; The null descriptor. + dw 0xFFFF ; Limit (low). + dw 0 ; Base (low). + db 0 ; Base (middle) + db 0 ; Access. + db 1 ; 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 10101111b ; Granularity, 64 bits flag, limit19:16. + 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. + +inline_enter_long_mode: ;;;;;;;;;;;;; section 1: paging ; disable paging in 32bit protected mode (if any) mov eax, cr0 @@ -116,6 +142,22 @@ _set_one_entry: or eax, 1 << 31 ; Set the PG-bit, which is the 32nd bit (bit 31). mov cr0, eax ; Set control register 0 to the A-register. + ;;;;;;;;;;;;;;;;; Section 3: enter 64bit long mode + lgdt [GDT64.Pointer] ; Load the 64-bit global descriptor table. + jmp GDT64.Code:Realm64 ; Set the code segment and enter 64-bit long mode. + +[BITS 64] + +Realm64: + cli ; Clear the interrupt flag. + mov ax, GDT64.Data ; Set the A-register to the data descriptor. + mov ds, ax ; Set the data segment to the A-register. + mov es, ax ; Set the extra segment to the A-register. + mov fs, ax ; Set the F-segment to the A-register. + mov gs, ax ; Set the G-segment to the A-register. + mov ss, ax ; Set the stack segment to the A-register. + ; done +