assemblyx86osdevprotected-modebochs

GPF after far jump to protected mode


After several weeks of work using GRUB as my bootloader I decided that I should roll my own so I can understand how they work. I found Brokenthorn's tutorials on the internet (currently on http://www.brokenthorn.com/Resources/OSDev9.html). When I try to switch to protected mode the cpu hardware resets after the far jump. I'm running bochs v. 2.6.

this is my second stage bootloader( almost a copy of the tutorial because i thought it would fix my problems - it doesn't)

    bits    16

; Remember the memory map-- 0x500 through 0x7bff is unused above the BIOS data area.
; We are loaded at 0x500 (0x50:0)

org 0x50:0x0

jmp main                ; go to start

;*******************************************************
;   Preprocessor directives
;*******************************************************

%include "Gdt.inc"          ; Gdt routines

;*******************************************************
;   Data Section
;*******************************************************


;*******************************************************
;   STAGE 2 ENTRY POINT
;
;       -Store BIOS information
;       -Load Kernel
;       -Install GDT; go into protected mode (pmode)
;       -Jump to Stage 3
;*******************************************************

main:

    ;-------------------------------;
    ;   Setup segments and stack    ;
    ;-------------------------------;

    cli             ; clear interrupts
    xor ax, ax          ; null segments
    mov ds, ax
    mov es, ax
    mov ax, 0x9000      ; stack begins at 0x9000-0xffff
    mov ss, ax
    mov sp, 0xFFFF
    sti             ; enable interrupts



    call    InstallGDT      ; install our GDT
    ;activate gate a20

    mov al,2
    out 0x92,al


    ;-------------------------------;
    ;   Go into pmode       ;
    ;-------------------------------;

    cli             ; clear interrupts
    mov eax, cr0        ; set bit 0 in cr0--enter pmode
    or  eax, 1
    mov cr0, eax
    jmp 08h:Stage3      ; ############It restarts here############

    ; Note: Do NOT re-enable interrupts! Doing so will triple fault!
    ; We will fix this in Stage 3.
;******************************************************
;   ENTRY POINT FOR STAGE 3
;******************************************************

bits 32                 ; Welcome to the 32 bit world!

Stage3:

    ;-------------------------------;
    ;   Set registers       ;
    ;-------------------------------;

    mov     ax, 0x10        ; set data segments to data selector (0x10)
    mov     ds, ax
    mov     ss, ax
    mov     es, ax
    mov     esp, 90000h     ; stack begins from 90000h


;*******************************************************
;   Stop execution
;*******************************************************

STOP:


    hlt

my GDT:

    gdt_data: 
    dd 0                ; null descriptor
    dd 0 

; gdt code:             ; code descriptor
    dw 0FFFFh           ; limit low
    dw 0                ; base low
    db 0                ; base middle
    db 10011010b            ; access
    db 11001111b            ; granularity
    db 0                ; base high

; gdt data:             ; data descriptor
    dw 0FFFFh           ; limit low (Same as code)
    dw 0                ; base low
    db 0                ; base middle
    db 10010010b            ; access
    db 11001111b            ; granularity
    db 0                ; base high

end_of_gdt:
toc: 
    dw end_of_gdt - gdt_data - 1    ; limit (Size of GDT)
    dd gdt_data             ; base of GDT

this is the error bochs gives when i try this code:

00018047272e[CPU0 ] jump_protected: gate type 0 unsupported
00018047272e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d)
00018047272e[CPU0 ] interrupt(): gate descriptor is not valid sys seg (vector=0x08)
00018047272i[CPU0 ] CPU is in protected mode (active)
00018047272i[CPU0 ] CS.mode = 16 bit
00018047272i[CPU0 ] SS.mode = 16 bit
00018047272i[CPU0 ] EFER   = 0x00000000
00018047272i[CPU0 ] | EAX=60000011  EBX=00000000  ECX=00090003  EDX=00000080
00018047272i[CPU0 ] | ESP=0000ffff  EBP=00000000  ESI=000e0000  EDI=0000ffac
00018047272i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af PF cf
00018047272i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00018047272i[CPU0 ] |  CS:0050( 0004| 0|  0) 00000500 0000ffff 0 0
00018047272i[CPU0 ] |  DS:0000( 0005| 0|  0) 00000000 0000ffff 0 0
00018047272i[CPU0 ] |  SS:9000( 0005| 0|  0) 00090000 0000ffff 0 0
00018047272i[CPU0 ] |  ES:0000( 0005| 0|  0) 00000000 0000ffff 0 0
00018047272i[CPU0 ] |  FS:0000( 0005| 0|  0) 00000000 0000ffff 0 0
00018047272i[CPU0 ] |  GS:0000( 0005| 0|  0) 00000000 0000ffff 0 0
00018047272i[CPU0 ] | EIP=0000004f (0000004f)
00018047272i[CPU0 ] | CR0=0x60000011 CR2=0x00000000
00018047272i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00018047272i[CPU0 ] 0x000000000000004f>> jmp far 0008:00a4 : EAA4000800
00018047272e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
00018047272i[SYS  ] bx_pc_system_c::Reset(HARDWARE) called
00018047272i[CPU0 ] cpu hardware reset

what can I to to fix this problem?


Solution

  • 0x000000000000004f>> jmp far 0008:00a4 : EAA4000800
    

    It looks like org 0x50:0x0 is messing things up, since that far jump should be more like 0008:05a4. Try org 0x500 instead of org 0x50:0x0.