Page 1 of 1

Triple fault when switch to protected mode

Posted: Mon Feb 08, 2016 7:11 pm
by msrojas
Hello. I'm writing a bootloader and at moment to switch to protected mode it cause a triple fault. Honestly I don't know why, I see everything "right". I've following tutorials, reading books and I don't understand why this doesn't work. Here is the code.

first stage

Code: Select all

org 0x7c00
bits 16 
start:	
	mov [DriveBoot], dl 
	xor ax, ax 
	mov ds, ax ;00:0x7c00
	
	cli
	mov ss, ax 
	mov sp, 0x200 
	sti           

	call ClearScreen

	cld 
	mov si, mensaje 
	call print 

	mov dl, 0x00 
	mov dh, 0x01
	call UpdateCursor 

	call LoadSecondSector 
	cld 
	mov si, SecondSectorLoaded 
	call print 

	mov dl, 0x00
	mov dh, 0x02 
	call UpdateCursor

	jmp 0x1000:0x0 ;65536

	hlt 

ClearScreen:
	mov ah, 0x00 
	mov al, 0x02 
	int 0x10
	ret	

UpdateCursor:
	mov ah, 0x02 
	int 0x10 
	ret	

LoadSecondSector:
	.Reset: 
		mov ah, 0 
		mov dl, [DriveBoot] 
		int 0x13 
		jc .Reset 

		mov bx, 0x1000 
		mov es, bx 
		xor bx, bx ;offset = 0

	.Load:
		mov ah, 0x02 
		mov al, 1
		mov ch, 0 
		mov cl, 2 
		mov dh, 0
		mov dl, [DriveBoot] 
		int 0x13 
		jc .Load 
	ret 

print:  
	lodsb  
	or al, al 
	jz .PrintDone 
	mov ah, 0eh 
	int 10h 
	jmp print 

.PrintDone:
	ret	 

mensaje: db "Bootloader cargado...",0
SecondSectorLoaded: db "Segundo sector cargado...",0
DriveBoot db 0
times 510 - ($-$$) db 0 
dw 0xAA55 
second stage

Code: Select all

org 0x0
bits 16

main:
	mov ax, cs 
	mov ds, ax 

	mov ax, 0x21
	cli
	mov ss, ax 
	mov sp, 0x200
	sti 

	cld 
	mov si, LoadingKernel
	call Print

	mov dl, 0x0
	mov dh, 0x03
	call updateCursor

	call enable_A20_Line
	cld 
	mov si, A20LineEnabled
	call Print

	cli 
	lgdt [toc]

	mov eax, cr0
	or eax, 0x01
	mov cr0, eax
	jmp 0x08:PMode_Entry ;Hear is the problem

	hlt	

updateCursor:
	mov ah, 0x02 
	int 0x10
	ret	

Esperar_Controller:
	in al, 0x64
	test al, 2
	jnz Esperar_Controller
	ret
Esperar_Controller_Data:
	in al, 0x64
	test al, 1
	jz Esperar_Controller_Data
	ret		

habilitar_A20_Line:
	cli
	call Esperar_Controller
	mov al, 0xad
	out 0x64, al

	call Esperar_Controller
	mov al, 0xd0
	out 0x64, al

	call Esperar_Controller_Data
	in al, 0x60
	push eax

	call Esperar_Controller
	mov al, 0xd1
	out 0x64, al

	call Esperar_Controller
	pop eax
	or al, 2
	out 0x60, al

	call Esperar_Controller
	mov al, 0xae
	out 0x64, al
	sti

	ret

Verificar_A20_Line:
	pushf
	push ds
	push es
	push di
	push si

	cli 

	xor ax, ax
	mov es, ax 
	mov di, 0x500

	mov ax, 0xffff
	mov ds, ax
	mov si, 0x510

	mov al, byte [es:di]
	push ax

	mov al, byte [ds:si]
	push ax

	mov byte [es:di], 0x00
	mov byte [ds:si], 0xff

	cmp byte [es:di], 0xff

	pop ax
	mov byte [ds:si], al

	pop ax
	mov byte [es:di], al

	mov ax, 0
	je .Verificar_A20_Line_exit
	mov ax, 1

.Verificar_A20_Line_exit:
	pop si
	pop di
	pop es
	pop ds
	popf
	sti
	ret

enable_A20_Line:
	call Verificar_A20_Line
	cmp ax, 0
	jne .A20_done
	call habilitar_A20_Line
	call Verificar_A20_Line
	cmp ax, 0
	jne .A20_done

	cld 
	mov si, ErrorA20Line
	call Print		

.A20_done:
	ret		

Print:
	lodsb   
	or al, al 
	jz .printDone
	mov ah, 0eh 
	int 10h 
	jmp Print 

.printDone:
	ret	 

gdt_data:
;NULL DESCRIPTOR
	dd 0
	dd 0
;Code descriptor
	dw 0xffff
	dw 0
	db 0
	db 0x9a
	db 0xcf
	db 0

;Data descriptor
	dw 0xffff
	dw 0
	db 0
	db 0x92
	db 0xcf
	db 0
end_of_gdt:

toc:
	dw end_of_gdt - gdt_data - 1
	dd gdt_data		

bits 32
PMode_Entry:
	mov ax, 0x10
	mov ds, ax
	mov es, ax
       ;For the moment until hear

	hlt	
	
LoadingKernel: db "Cargando el kernel...",0
A20LineEnabled: db "A20 Line habilitado",0
ErrorA20Line: db "Error al habilitar A20 line", 0	
	
times 512 - ($-$$) db 0	

Re: Triple fault when switch to protected mode

Posted: Mon Feb 08, 2016 11:01 pm
by Octocontrabass
Your code is full of bugs. I'm surprised you've managed to get this far without having any other problems.

Code: Select all

start:
	mov [DriveBoot], dl
	xor ax, ax
	mov ds, ax ;00:0x7c00

	cli
	mov ss, ax
	mov sp, 0x200
	sti
The instruction "mov [DriveBoot], dl" writes DL to the memory at DS:DriveBoot. Since you haven't set DS yet, this could be anywhere. You must set DS before executing any instructions that rely on the value in DS.

You are setting the stack to 0x0000:0x0200, but that memory is already in use by the IVT. You need to put your stack somewhere else.

Code: Select all

	mov ax, 0x21
	cli
	mov ss, ax
	mov sp, 0x200
	sti
Now you're setting the stack to 0x0021:0x0200. That memory is in use by the BDA, and when your stack grows, it overwrites the IVT as well. You really need to find somewhere better to put your stack.

Code: Select all

toc:
	dw end_of_gdt - gdt_data - 1
	dd gdt_data
The GDTR requires a linear address. The assembler generates segment-relative offsets. When the segment base is 0, linear addresses and segment-relative offsets are the same, but your segment base is not 0. You either need to move your code so that the segment base is 0, or adjust the address in your GDTR to take into account the segment base.

Re: Triple fault when switch to protected mode

Posted: Mon Feb 08, 2016 11:35 pm
by msrojas
Oh god, many bugs. And very thanks for the reply, I realized of many things with your answer (specially about the stack). I'm not in the computer right now, but I will correct the code as soon as possible. Thanks

Re: Triple fault when switch to protected mode

Posted: Tue Feb 09, 2016 2:58 pm
by msrojas
Ok, I've corrected and now "works". But I don't know if this is fine, so I would appreciate if you check.

I saw the memory map, so there is no problem if I put my stacks in this way, right?

Code: Select all

;Stack of first stage
mov ax, 0x200 
cli
mov ss, ax ;It would be 0x2000:200
mov sp, 0x200 
sti 

;...

;Stack of second stage
mov ax, 0x221
cli
mov ss, ax ;0x2210:200
mov sp, 0x200 
sti 
Also I changed the segment of the second stage. Now is 0x0:0x8000.

Code: Select all

;This is inside of the procedure "LoadSecondSector" of the first stage
mov bx, 0x0000 
mov es, bx 
mov bx, 0x8000 
With that it works, but there is maybe something wrong, since when I call the procedure "LoadSecondSector" in the first stage the cursor doesn't work anymore. But as I said before, it switch to protected mode without problems.
So what makes the cursor does not work?

Re: Triple fault when switch to protected mode

Posted: Tue Feb 09, 2016 4:21 pm
by Octocontrabass

Code: Select all

mov ss, ax ;It would be 0x2000:200
It will be 0x0200:0x0200.

Code: Select all

mov ss, ax ;0x2210:200
0x0221:0x0200.

These are strange places to put your stack, but that memory is free for you to use, so the location isn't a problem. I think 0x200 bytes is too small to call some BIOS functions, but it's hard to find a real minimum.
msrojas wrote:So what makes the cursor does not work?
The BIOS function you are using uses AH, BH, and DX as input. Do you set all of these registers before calling the BIOS?

Re: Triple fault when switch to protected mode

Posted: Tue Feb 09, 2016 5:00 pm
by msrojas
I'm a little confuse. The segments are shifted by 4, so.

Code: Select all

0x200 * 16 = 0x2000 ;right?


And about the cursor, I set the register like this.

Code: Select all

mov dl, 0x0
mov dh, 0x2
call UpdateCursor

UpdateCursor:
    mov ah, 0x02
    int 0x10
    ret 
At beginnig of the bootloader it works, but after to load a new sector it doesn't work anymore.

Re: Triple fault when switch to protected mode

Posted: Tue Feb 09, 2016 5:26 pm
by Octocontrabass
msrojas wrote:I'm a little confuse. The segments are shifted by 4, so.

Code: Select all

0x200 * 16 = 0x2000 ;right?
The segment is 0x200. The base is 0x2000. Real-mode addresses are written as segment:offset pairs, not base:offset pairs. If you don't follow the standards used by other programmers, you'll get confused more easily.
msrojas wrote:And about the cursor, I set the register like this.
Octocontrabass wrote:The BIOS function you are using uses AH, BH, and DX as input. Do you set all of these registers before calling the BIOS?
I already know the answer to this question. I'm asking because you should be able to figure it out. You won't learn if I give you all the answers!

Re: Triple fault when switch to protected mode

Posted: Wed Feb 10, 2016 8:55 pm
by msrojas
Ok, I've busy and I'm not in the computer, but seeing the code that I've corrected, I suppose that the error in the cursor is caused by the register bx. But I'm not sure, I can't test the code right now