Page 1 of 1

Bootloader (PMode) issue.

Posted: Wed Nov 14, 2007 1:29 am
by 01000101
I've got most of the bootloader good to go, but I am having a really difficult time with the far jump into actual 32-bits land. Here is my main code of the second stage loader. Ask if you need to see my gdt tables. Also at the bottom is the BOCHS output of the CPU.

My stage2 loader:

Code: Select all

bits 16
org 0x0

jmp start_real_mode

%include "gdt.inc"				

start_real_mode:

    cli
    push cs				; CS == 0x0050 (which is where we are after first stage boot)
    pop ds              ; Set DS == CS

                        ;enabling A20 
try1: 
    in al, 0x64 
    test al, 2 
    jnz try1 
    mov al, 0xD1 
    out 0x64, al 
try2: 
    in al, 0x64 
    and ax, byte 2 
    jnz try2 
    mov al, 0xDF 
    out 0x60, al 

    cli                 ;disable interrupts 
    
    lgdt [_gdt] 

                        ;enter protected mode 
    mov eax, cr0 
    or eax,1 
    mov cr0, eax 
    
    cli                 ; just to make sure 
    
    jmp	0x8:Stage3		; far jump to fix CS. Remember that the code selector is 0x8!

;******************************************************
;	PROTECTED MODE!
;******************************************************

[bits 32]					; Welcome to the 32 bit world!

Stage3:

    mov eax, 0x10           ; set correct selectors
    mov ds, ax 
    mov es, ax 
    mov fs, ax 
    mov gs, ax 
    mov ss, ax 
    
    mov esp, 0xA0000       ;use this area for stack (640KB->0KB) 

    hlt
BOCHS debugging:

Code: Select all

00002065996i[BIOS ] Booting from 0000:7C00
00002900487e[CPU0 ] check_cs: not a valid code segment !
00002900487i[CPU0 ] protected mode
00002900487i[CPU0 ] CS.d_b = 16 bit
00002900487i[CPU0 ] SS.d_b = 16 bit
00002900487i[CPU0 ] EFER   = 0x00000000
00002900487i[CPU0 ] | RAX=0000000000000011  RBX=0000000000000203
00002900487i[CPU0 ] | RCX=0000000000000003  RDX=0000000000000fff
00002900487i[CPU0 ] | RSP=000000000000fffb  RBP=0000000000000000
00002900487i[CPU0 ] | RSI=00000000ffff01c5  RDI=0000000000080005
00002900487i[CPU0 ] |  R8=0000000000000000   R9=0000000000000000
00002900487i[CPU0 ] | R10=0000000000000000  R11=0000000000000000
00002900487i[CPU0 ] | R12=0000000000000000  R13=0000000000000000
00002900487i[CPU0 ] | R14=0000000000000000  R15=0000000000000000
00002900487i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af PF cf
00002900487i[CPU0 ] | SEG selector     base    limit G D
00002900487i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00002900487i[CPU0 ] |  CS:0050( 0004| 0|  0) 00000500 0000ffff 0 0
00002900487i[CPU0 ] |  DS:0050( 0005| 0|  0) 00000500 0000ffff 0 0
00002900487i[CPU0 ] |  SS:0000( 0005| 0|  0) 00000000 0000ffff 0 0
00002900487i[CPU0 ] |  ES:0050( 0005| 0|  0) 00000500 0000ffff 0 0
00002900487i[CPU0 ] |  FS:07c0( 0005| 0|  0) 00007c00 0000ffff 0 0
00002900487i[CPU0 ] |  GS:07c0( 0005| 0|  0) 00007c00 0000ffff 0 0
00002900487i[CPU0 ] |  MSR_FS_BASE:0000000000007c00
00002900487i[CPU0 ] |  MSR_GS_BASE:0000000000007c00
00002900487i[CPU0 ] | RIP=0000000000000052 (0000000000000052)
00002900487i[CPU0 ] | CR0=0x00000011 CR1=0x0 CR2=0x0000000000000000
00002900487i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00002900487i[CPU0 ] >> jmp far 0008:0057 : EA57000800
00002900487e[CPU0 ] exception(): 3rd (13) exception with no resolution, shutdown status is 00h, resetting
Shouldn't CS be correct after the far jump???

Posted: Wed Nov 14, 2007 2:41 am
by AJ
Yes - I think we need to see your GDT. The error is that CS is not a valid code segment selector - check that you haven't inadvertently set up the first GDT entry as a data segment rather than a code segment.

Cheers,
Adam

Posted: Wed Nov 14, 2007 5:21 am
by Dex
You should post your "gdt.inc", so we can see your selector .

Posted: Wed Nov 14, 2007 3:21 pm
by 01000101
for some reason after I re-compiled today (w/o altering anything) I get a similar error, but it is still a bit different in the bochs debugging, ill post it after the GDT.inc.

gdt.inc:

Code: Select all

bits 16
    
_gdt: 
   dw gdt_end - gdt_start - 1 ;gdt size 
   dd gdt_start               ;gdt address 
      
gdt_start:                    ; Address for the start of the GDT 

gdt_null:               ; Null Segment 
        dd 0 
        dd 0 

gdt_code:               ; Code segment, read/execute 
        dw 0FFFFh       ; LIMIT 0-15 = 0xFFFF 
        dw 0            ; BASE 0-15 = 0 
        db 0            ; BASE 16-23 
        db 10011010b    ; P=1, DPL=00, S=1, Type=1010 (Code Read/Execute) 
        db 11001111b    ; G=1 (4kb unit), D=1, 0, AVL=1, LIMIT 16-19 = 0xF 
        db 0            ; BASE 31-24 = 0 

gdt_data:               ; Data segment, read/write 
        dw 0FFFFh       ; LIMIT 0-15 = 0xFFFF 
        dw 0            ; BASE 0-15 = 0 
        db 0            ; BASE 16-23 
        db 10010010b    ; P=1, DPL=00, S=1, Type=0010 (Data Read/Write) 
        db 11001111b    ; G=1 (4kb unit), D=1, 0, AVL=1, LIMIT 16-19 = 0xF 
        db 0            ; BASE 31-24 = 0 

gdt_end:                ; Address for the end of the GDT

BOCHS debugging:

Code: Select all

00002065996i[BIOS ] Booting from 0000:7C00
00002900487e[CPU0 ] jump_protected: call gate.p == 0
00002900487e[CPU0 ] fetch_raw_descriptor: GDT: index (f007)1e00 > limit (17)
00002900487i[CPU0 ] protected mode
00002900487i[CPU0 ] CS.d_b = 16 bit
00002900487i[CPU0 ] SS.d_b = 16 bit
00002900487i[CPU0 ] EFER   = 0x00000000
00002900487i[CPU0 ] | RAX=0000000000000011  RBX=0000000000000203
00002900487i[CPU0 ] | RCX=0000000000000003  RDX=0000000000000fff
00002900487i[CPU0 ] | RSP=000000000000fffb  RBP=0000000000000000
00002900487i[CPU0 ] | RSI=00000000ffff01c5  RDI=0000000000080005
00002900487i[CPU0 ] |  R8=0000000000000000   R9=0000000000000000
00002900487i[CPU0 ] | R10=0000000000000000  R11=0000000000000000
00002900487i[CPU0 ] | R12=0000000000000000  R13=0000000000000000
00002900487i[CPU0 ] | R14=0000000000000000  R15=0000000000000000
00002900487i[CPU0 ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af PF cf
00002900487i[CPU0 ] | SEG selector     base    limit G D
00002900487i[CPU0 ] | SEG sltr(index|ti|rpl)     base    limit G D
00002900487i[CPU0 ] |  CS:0050( 0004| 0|  0) 00000500 0000ffff 0 0
00002900487i[CPU0 ] |  DS:0050( 0005| 0|  0) 00000500 0000ffff 0 0
00002900487i[CPU0 ] |  SS:0000( 0005| 0|  0) 00000000 0000ffff 0 0
00002900487i[CPU0 ] |  ES:0050( 0005| 0|  0) 00000500 0000ffff 0 0
00002900487i[CPU0 ] |  FS:07c0( 0005| 0|  0) 00007c00 0000ffff 0 0
00002900487i[CPU0 ] |  GS:07c0( 0005| 0|  0) 00007c00 0000ffff 0 0
00002900487i[CPU0 ] |  MSR_FS_BASE:0000000000007c00
00002900487i[CPU0 ] |  MSR_GS_BASE:0000000000007c00
00002900487i[CPU0 ] | RIP=000000000000004c (000000000000004c)
00002900487i[CPU0 ] | CR0=0x00000011 CR1=0x0 CR2=0x0000000000000000
00002900487i[CPU0 ] | CR3=0x00000000 CR4=0x00000000
00002900487i[CPU0 ] >> jmp far 0008:0051 : EA51000800

Posted: Thu Nov 15, 2007 4:41 am
by Combuster

Code: Select all

_gdt:
   dw gdt_end - gdt_start - 1 ;gdt size
   dd gdt_start               ;gdt address 

Code: Select all

; CS == 0x0050 (which is where we are after first stage boot)

Code: Select all

org 0x0 
you assembled gdt_start relative to the start of the binary. however, the processor expects a linear address.

in essence, you tell the processor to find the gdt at gdt_start, while it is at CS * 16 + gdt_start (= gdt_start + 0x500)