Of course Interrupts are disabled. I've no idea, what's going wrong, so I'm posting my complete 2nd bootloader code. Maybe I've missed something:
Code: Select all
org 0x0
bits 16
; cs was set by the bootloader before jumping to this code
cli ; clear interrupts
push cs ; Insure DS=CS
push cs
pop ds
pop es
sti
;************************************************
; Activating 32 Bit Protected Mode
;************************************************
mov ax, 0x0000
mov es, ax
mov word [es:0x0000], ds
xor ebx,ebx
mov bx,ds ; BX = segment
shl ebx,4 ; BX = "linear" address of segment base
mov eax,ebx
mov [gdt2 + 2],ax ; set base address of 32-bit segments
mov [gdt3 + 2],ax
mov [gdt4 + 2],ax ; set base address of 16-bit segments
mov [gdt5 + 2],ax
mov [gdt1_x64 + 2],ax
mov [gdt2_x64 + 2],ax
shr eax,16
mov [gdt2 + 4],al
mov [gdt3 + 4],al
mov [gdt4 + 4],al
mov [gdt5 + 4],al
mov [gdt1_x64 + 4],al
mov [gdt2_x64 + 4],al
mov [gdt2 + 7],ah
mov [gdt3 + 7],ah
mov [gdt4 + 7],ah
mov [gdt5 + 7],ah
mov [gdt1_x64 + 7],ah
mov [gdt2_x64 + 7],ah
lea eax,[gdt + ebx] ; Now EAX contains the physical address of the x86 GDT
mov [gdtr + 2],eax
lea eax,[gdt_x64 + ebx] ; Now EAX contains the physical address of the x64 GDT
mov [gdtr_x64 + 2],eax
lea eax,[start_of_idt + ebx] ; Now EAX contains the physical address of the x86 IDT
mov [idt_pointer + 2],eax
pushad ; Save cursor line
mov ah, 0x03
mov bh, 0x00
int 0x10
mov byte [cursor_pos], dh
mov ah, 0x02 ; Hide cursor
mov bh, 0x00
mov dl, 0x00
mov dh, 0x19
int 0x10
popad
cli ; Disable interrupts
xor ax,ax
mov es,ax
mov edx,[es:0x0D * 4] ; INT 0Dh vector -> EDX
mov [es:0x0D * 4 + 2],cs
lea ax,[trap]
mov [es:0x0D * 4],ax
; Store real mode instruction pointer and code segment.
mov ax,cs
mov [RealModeCS],ax
lea ax,[do_rm]
mov [RealModeIP],ax
; Loading temporary GDT and IDT
lgdt [gdtr]
lidt [idt_pointer]
; Activating 32-Bit Protected Mode
mov eax,cr0
or al,1
mov cr0,eax
jmp SYS_CODE_SEL:do_pm ; FAR-JMP into 32-Bit code segment
; Real-mode interrupt 0Dh handler:
trap:
mov ax,0xB800
mov fs,ax
mov byte [fs:0x9C],'!'
pop ax ; point stacked IP beyond...
add ax,5 ; ...the offending instruction
push ax
iret
;************************************************
;* Now we are in 32 Bit protected mode
;************************************************
[BITS 32]
do_pm:
xor edi,edi
xor esi,esi
; Load 32-Bit protected mode selectors
mov ax, SYS_DATA_SEL
mov ds, ax
mov ss, ax
; Load linear code segment descriptor
mov ax, LINEAR_SEL
mov es, ax
mov fs, ax
mov gs, ax
; Stack
mov esp, 0x00001000
; Check if the CPU supports 64 Bit long mode.
; If not the boot proccess gets canceled
mov eax, 80000000h
cpuid
cmp eax, 80000000h
jbe no_long_mode
mov eax, 80000001h
cpuid
bt edx, 29
jnc no_long_mode
jmp long_ok
no_long_mode:
hlt
long_ok:
; Enabling 64 Bit long mode in five steps
; Step one: Activating the physical address extension (PAE)
mov eax, cr4
bts eax, 5
mov cr4, eax
; Step two: Load PML4
call setup_pml4
mov eax, 0x300000 ; Pointer to PML4 table (located at 3 MB mark).
mov cr3, eax
; Step three: Enabling IA-32e mode
mov ecx, 0xC0000080
rdmsr
bts eax, 8
wrmsr
;Step four: Enabling paging
mov eax, cr0
bts eax, 31
mov cr0, eax
; Step five: Jump into 64 Bit long mode code region
lgdt[gdtr_x64]
jmp SYS_DATA_SEL_X64:do_lm
;************************************************
;* RealMode Data
;************************************************
do_rm:
RealModeIP:
dw 0
RealModeCS:
dw 0
;************************************************
;* Includes (x86)
;************************************************
%include './hardware/cpu/gdt.inc'
%include './hardware/cpu/gdt_x64.inc'
%include './hardware/cpu/idt.inc'
%include "./hardware/cpu/pml4.inc"
;************************************************
;* Now we are in 64 Bit long mode
;************************************************
[BITS 64]
do_lm:
hlt
gdt.inc:
Code: Select all
gdtr: dw gdt_end - gdt - 1 ; GDT limit
dd gdt ; (GDT base gets set above)
;************************************************
; Global descriptor table (GDT) (just temporary)
;************************************************
; null descriptor
NULL_SEL equ 00h
gdt: dw 0 ; limit 15:0
dw 0 ; base 15:0
db 0 ; base 23:16
db 0 ; type
db 0 ; limit 19:16, flags
db 0 ; base 31:24
; linear data segment descriptor
LINEAR_SEL equ $-gdt
dw 0xFFFF ; limit 0xFFFFF
dw 0 ; base 0
db 0
db 0x92 ; present, ring 0, data, expand-up, writable
db 0xCF ; page-granular, 32-bit
db 0
; code segment descriptor
SYS_CODE_SEL equ $-gdt
gdt2: dw 0xFFFF ; limit 0xFFFFF
dw 0 ; (base gets set above)
db 0
db 0x9A ; present, ring 0, code, non-conforming, readable
db 0xCF ; page-granular, 32-bit
db 0
; data segment descriptor
SYS_DATA_SEL equ $-gdt
gdt3: dw 0xFFFF ; limit 0xFFFFF
dw 0 ; (base gets set above)
db 0
db 0x92 ; present, ring 0, data, expand-up, writable
db 0xCF ; page-granular, 32-bit
db 0
; a code segment descriptor that is 'appropriate' for real mode
; (16-bit, byte-granular, limit=0xFFFF)
REAL_CODE_SEL equ $-gdt
gdt4: dw 0xFFFF
dw 0 ; (base gets set above)
db 0
db 0x9A ; present, ring 0, code, non-conforming, readable
db 0 ; byte-granular, 16-bit
db 0
; a data segment descriptor that is 'appropriate' for real mode
; (16-bit, byte-granular, limit=0xFFFF)
REAL_DATA_SEL equ $-gdt
gdt5: dw 0xFFFF
dw 0 ; (base gets set above)
db 0
db 0x92 ; present, ring 0, data, expand-up, writable
db 0 ; byte-granular, 16-bit
db 0
gdt_end:
gdt_x64.inc:
Code: Select all
gdtr_x64: dw gdt_end_x64 - gdt_x64 - 1 ; GDT limit
dq gdt_x64 ; (GDT base gets set above)
;************************************************
; Global descriptor table for x64 mode (GDT)
;************************************************
gdt_x64:
dw 0
dw 0
db 0
db 0
db 0
db 0
LINEAR_SEL_X64 equ $-gdt_x64
dw 0xFFFF
dw 0x0000
db 0x00
db 10010010b
db 0xAF
db 0x00
SYS_CODE_SEL_X64 equ $-gdt_x64
gdt1_x64:
dw 0xFFFF
dw 0x0000
db 0x00
db 10011010b
db 0xAF
db 0x00
SYS_DATA_SEL_X64 equ $-gdt_x64
gdt2_x64:
dw 0xFFFF
dw 0x0000
db 0x00
db 10010010b
db 0xAF
db 0x00
gdt_end_x64: