Page 1 of 1

Restart loop in bochs after enabling pMode

Posted: Tue Sep 16, 2014 6:29 am
by Mtype2
Hello...i started fiddling with a custom os bootloader some days ago.. my goal is to load a c kernel(_sys_entry) after setting gdt and stuff...
but unfortunately icant even reach the jmp to x32(a label that contains 32bit code which i deleted in the screenshots...simply i replaced it with the jmp $ )
bochs gives me the following error:

Booting from 0000:7c00
interrupt(): gate descriptor is not valid sys seg(0x08)
interrupt(): gate descriptor is not valid sys seg(0x0d)
interrupt(): gate descriptor is not valid sys seg(0x08)
CPU is in pmode(active)

heres the code:
Image

basically im reading the second sector of the img and loading it to 0x1000 and then jumping to it

please help me im going crazy with this stuff...

Re: Restart loop in bochs after enabling pMode

Posted: Tue Sep 16, 2014 8:07 am
by Octocontrabass
Combuster's crystal ball says you're receiving an interrupt before you've set up your interrupt handler.

Re: Restart loop in bochs after enabling pMode

Posted: Tue Sep 16, 2014 9:47 am
by Mtype2
Ok...so am i suposed to set up an IDT? if so than how?,is there any way to avoid recieving the interrupt? cuz i just want a simple coded loader and do the major stuff in c...


EDIT: avoided the error by putting

Code: Select all

cli 
right before

Code: Select all

mov eax, cr0 
,but now i have another problem..when i perform

Code: Select all

jmp code:x32
it gives another error :/

Re: Restart loop in bochs after enabling pMode

Posted: Tue Sep 16, 2014 11:59 am
by Octocontrabass
The crystal ball says "try again later". Hmm.

While we're waiting, why don't you improve your posting style a little bit? It's hard to read code in images like that. It'd be a lot easier for us to help you if you post your code as text, in between code tags kind of like this:

[code]
mov eax, cr0
or al, 1
mov cr0, eax
[/code]

It's also a good idea to include the error messages from Bochs, if there are any.

Re: Restart loop in bochs after enabling pMode

Posted: Tue Sep 16, 2014 12:15 pm
by Mtype2
BOOTZ.asm:

Code: Select all

%define ADDR 0x1000
%define Drive 0x00
%define SectorAmount 1
%define Cylinder 0
%define Sector 2
%define Head 0

[BITS 16]
[ORG 0]

jmp 07C0h:reset         ; Goto segment 07C0

reset:                      
    mov ah, 0               ;Reset FLP OPcode
    mov dl, Drive           ;Drive Num(0-A:)
    int 13h                 ;Floppy int
    jc reset                ;ERROR => reset again
buf:
    mov ax, ADDR            ; ES:BX = 1000:0000
    mov es, ax              ;
    mov bx, 0               ;
read:
    mov ah, 2               ; Read
    mov al, SectorAmount    ; number of sectors
    mov ch, Cylinder        ; cylinder number
    mov cl, Sector          ; sector number
    mov dh, Head            ; head number
    int 13h                 ; Read!
    mov ah,0Ah
    mov al,'!'
    mov cx,12
    int 0x10
    mov ah,0x00
    int 16h
    jmp ADDR:0x00

times 510-($-$$) db 0
dw 0AA55h
CORELD.asm:

Code: Select all

[BITS 16]
jmp init

string1 db 'Succesfully loaded CORELD,Initializing Kernel... '
string2 db 'GDT has been set succesfully...                  '
string3 db 'A20 Enabled...                                   '
string4 db 'PMODE has been set succesfully...                '
string5 db 'PC is now ready to run the kernel in 32 bit mode.'
%include "C:\Users\Mark\Desktop\OS\source\gdt.inc"			; Gdt routines

echo:
	add dh,1
	mov ah,13h
	mov al,1
	mov bl,0x02
	mov cx,49
	mov bp,si
	int 10h
	ret
init:
	mov ah,0x00
	mov al,3h
	int 0x10	
	mov si,string1
	call echo
memmap:
	cli
	lgdt [gdt_point]
	mov si,string2
	call echo
set32bit:
	mov ah,0x00
    int 16h
    mov si,string4
	call echo
	mov si,string5
	call echo
	mov eax, cr0 
	or  eax, 1     ; set PE (Protection Enable) bit in CR0 (Control Register 0)
	mov cr0, eax
	jmp 08h:x32

[BITS 32]
x32:
	mov ax, 0x10
	mov ds, ax
	mov es, ax
	mov gs, ax
	mov fs, ax
	mov gs, ax
	mov ss, ax
	mov esp,0x00FFFFFF
	hlt


times 512-($-$$) db 0
gdt.inc:

Code: Select all

[BITS 16]
gdt_start:
	dd 0
	dd 0
	;CodeSeg:
	code equ $-gdt_start
	dw 0xFFFF
	dw 0
	db 0
	db 10011010b
	db 11001111b
	db 0
	;Dataseg:
	data equ $-gdt_start
	dw 0xFFFF
	dw 0
	db 0
	db 10011010b
	db 11001111b
	db 0
gdt_point:
	dw gdt_point - gdt_start - 1
	dd gdt_start

as you suggested i added the

Code: Select all

cli 
in CORELD in memmap.
however,when i jump to x32 after setting pmode i get a restart and the following message... if i just put hlt after pmode everything is ok... so iguess the problem is in the jmp offset or something:

Image

probably a wrong offset as i cant get their idea...(gate 0 unsuported)

so how one can jump to the 32bit code after setting pmode? thanks in advance

Re: Restart loop in bochs after enabling pMode

Posted: Tue Sep 16, 2014 2:24 pm
by Octocontrabass

Code: Select all

gdt_point:
   dw gdt_point - gdt_start - 1
   dd gdt_start
What value does the assembler output for gdt_start?

Why does it output the wrong value?

Re: Restart loop in bochs after enabling pMode

Posted: Tue Sep 16, 2014 3:15 pm
by Mtype2
How am i suposed to check that?...

i tried adding [ORG 0x10000] to CORELD but it didnt do the trick...

i should somehow offset the adress to which the img data is read to the gdt right?(like dd gdt_start + 0x1000)

Re: Restart loop in bochs after enabling pMode

Posted: Wed Sep 17, 2014 3:18 am
by Octocontrabass
Mtype2 wrote:How am i suposed to check that?...
Have your assembler output a list file, or just open the file in a hex editor.
Mtype2 wrote:i tried adding [ORG 0x10000] to CORELD but it didnt do the trick...
The org statement tells the assembler the offset of the start of the file. The problem you're having is that the offset is relative to a base address, and different parts of CORELD are using different base addresses. The real mode code uses a base address of 0x10000, the GDTR always uses a base address of 0, and the protected mode code uses a base address of 0.
Mtype2 wrote:i should somehow offset the adress to which the img data is read to the gdt right?(like dd gdt_start + 0x1000)
It's possible to fix up offsets that are relative to one base address to be relative to a different base address, but it's a lot easier if you use zero for the base address everywhere.

For example, making BOOTZ use 0 for its base address is straightforward:

Code: Select all

[ORG 0x7C00]

jmp 0:reset
To do the same to CORELD, you'll have to load it at a different address.

Re: Restart loop in bochs after enabling pMode

Posted: Wed Sep 17, 2014 4:23 am
by Combuster
Octocontrabass wrote:The crystal ball says "try again later".
Divination is an art, and you obviously missed the user manual. Now give it back because it needs charging.

Not that much divination seems to be needed in this case, though.

GDTs take a linear address - or in this case that equals the physical address. The app is however segmented with org=0 and seg>0 (if ADDR was zero, you'd already have overwritten your IVT and break a lot of other things), so any offsets you're using are relative to the start of your binary, rather than the start of memory as is needed.

Also, since you seem to have one of those silly microsoft terminals, right click on it, select the "mark" option, grab the block of text, press enter, and then paste the result in plain text in your post rather than taking and cropping an image. You can also configure bochs to write logs to a textfile, rather than the console screen, which is incredibly useful if you have more than one screen of relevant details.

Re: Restart loop in bochs after enabling pMode

Posted: Wed Sep 17, 2014 6:44 am
by Mtype2
Changed CORELD to:

Code: Select all

[BITS 16]
jmp 0x1000:init

string1 db 'Succesfully loaded CORELD,Initializing Kernel... '
string2 db 'GDT has been set succesfully...Press to set PMODE'
string3 db 'A20 Enabled...                                   '
string4 db 'PMODE has been set succesfully...                '
string5 db 'PC is now ready to run the kernel in 32 bit mode.'
%include "C:\Users\Mark\Desktop\OS\source\gdt.inc"			; Gdt routines

echo:
	add dh,1
	mov ah,13h
	mov al,1
	mov bl,0x0F
	mov cx,49
	mov bp,si
	int 10h
	ret
init:
	mov ah,0x00
	mov al,3h
	int 0x10	
	mov si,string1
	call echo
a20_line:
	mov	al, 2
	out	0x92, al
	mov si,string3
	call echo
memmap:
	cli
	mov ax,cs
	mov ds,ax
	mov ss,ax
	mov fs,ax
	mov gs,ax
	lgdt [gdt_point]
	mov si,string2
	call echo
set32bit:
	mov ah,0x00
    int 16h
    mov si,string4
	call echo
	mov si,string5
	call echo
	mov eax, cr0 
	or  eax, 1     ; set PE (Protection Enable) bit in CR0 (Control Register 0)
	mov cr0, eax
	jmp code:x32

[BITS 32]
x32:
	hlt


times 512-($-$$) db 0
now i get a new error:

Code: Select all

00005574167d[CPU0  ] protected mode activated
00005574171d[CPU0  ] BxError: Encountered an unknown instruction (signalling #UD)
00005574171i[CPU0  ] 0x0000000000000174>> (invalid)  : FFFF
00005574171d[CPU0  ] exception(0x06): error_code=0000
00005574171d[CPU0  ] interrupt(): vector = 06, TYPE = 3, EXT = 1
00005574171e[CPU0  ] interrupt(): gate.type(9) != {5,6,7,14,15}
00005574171d[CPU0  ] exception(0x0d): error_code=0032
00005574171d[CPU0  ] interrupt(): vector = 0d, TYPE = 3, EXT = 1
00005574171e[CPU0  ] interrupt(): gate descriptor is not valid sys seg (vector=0x0d)
00005574171d[CPU0  ] exception(0x0d): error_code=006a
00005574171d[CPU0  ] exception(0x08): error_code=0000
00005574171d[CPU0  ] interrupt(): vector = 08, TYPE = 3, EXT = 1
00005574171e[CPU0  ] interrupt(): gate descriptor is not valid sys seg (vector=0x08)
00005574171d[CPU0  ] exception(0x0d): error_code=0042
00005574171i[CPU0  ] CPU is in protected mode (active)
00005574171i[CPU0  ] CS.mode = 32 bit
00005574171i[CPU0  ] SS.mode = 16 bit
00005574171i[CPU0  ] EFER   = 0x00000000
00005574171i[CPU0  ] | EAX=60000011  EBX=0000000f  ECX=00090031  EDX=00000500
00005574171i[CPU0  ] | ESP=0000ffd6  EBP=000000c9  ESI=000e00c9  EDI=0000ffac
00005574171i[CPU0  ] | IOPL=0 id vip vif ac vm RF nt of df if tf sf zf af PF cf
00005574171i[CPU0  ] | SEG sltr(index|ti|rpl)     base    limit G D
00005574171i[CPU0  ] |  CS:0008( 0001| 0|  0) ffc0003d 0003f000 0 1
00005574171i[CPU0  ] |  DS:1000( 0005| 0|  0) 00010000 0000ffff 0 0
00005574171i[CPU0  ] |  SS:1000( 0005| 0|  0) 00010000 0000ffff 0 0
00005574171i[CPU0  ] |  ES:1000( 0005| 0|  0) 00010000 0000ffff 0 0
00005574171i[CPU0  ] |  FS:1000( 0005| 0|  0) 00010000 0000ffff 0 0
00005574171i[CPU0  ] |  GS:1000( 0005| 0|  0) 00010000 0000ffff 0 0
00005574171i[CPU0  ] | EIP=00000174 (00000174)
00005574171i[CPU0  ] | CR0=0x60000011 CR2=0x00000000
00005574171i[CPU0  ] | CR3=0x00000000 CR4=0x00000000
00005574171i[CPU0  ] 0x0000000000000174>> (invalid)  : FFFF
Lol i really want to get it working...and i'm just a beginner

Re: Restart loop in bochs after enabling pMode

Posted: Wed Sep 17, 2014 7:24 am
by Octocontrabass
Mtype2 wrote:Changed CORELD to:
You've basically fixed everything except the problem I pointed out.
Mtype2 wrote:now i get a new error:

Code: Select all

00005574171i[CPU0  ] | SEG sltr(index|ti|rpl)     base    limit G D
00005574171i[CPU0  ] |  CS:0008( 0001| 0|  0) ffc0003d 0003f000 0 1
This is because gdt_start is still wrong. You can either change your code so that the real-mode segments have a base of 0 instead of 0x10000, or kludge all of the offsets.

Re: Restart loop in bochs after enabling pMode

Posted: Wed Sep 17, 2014 10:34 am
by Mtype2
After adding:

Code: Select all

jmp 0x1000:init

Code: Select all

jmp DWORD code:x32+0x10000

Code: Select all

dd gdt_start + 0x10000
i have succesfully reached the x32 label...however it is a hardcoded hack...

i cant seem to make the base adress 0 no matter what i do...but its the more gentle way of doing it... right?
so how one can set the base adress to 0 if BOOTZ is loaded at 0? if i load the CORELD to 0 it just replaces the bootloader and does nothing...

Re: Restart loop in bochs after enabling pMode

Posted: Wed Sep 17, 2014 12:11 pm
by Octocontrabass
Mtype2 wrote:i cant seem to make the base adress 0 no matter what i do...but its the more gentle way of doing it... right?
In real mode, the base address of the segment is the value in the segment register multiplied by 0x10.

Make the base address 0 by using 0 for CS/DS/ES.