Page 1 of 2

Working on bochs but not on real PC

Posted: Thu Jan 24, 2008 7:27 am
by AlfaOmega08
Why does my OS work on bochs, but on real PC it doesn't?

On a real PC it reboots immediately after the bootstrap
On Virtual PC 2007 after the bootstrap, the virtual machine crashes...
Maybe is the boot code?

Posted: Thu Jan 24, 2008 8:01 am
by ucosty
VM's typically zero all the memory. A real computer may have random values scattered throughout ram. You can't rely on uninitialised variables containing 0.

VM's also dont accurately simulate the timings of devices and as a result IO operations can work fine in VMs but not on real machines. The solution is to add wait states around appropriate io port operations.

Thats all I can think of at the moment.

Posted: Thu Jan 24, 2008 8:16 am
by AlfaOmega08
So.. according to you, I should initialize each variable with 0. And add a wait after each I/O operation, like that:

Code: Select all

outportb(xxx, xxx);
for (i = 0; i < 500; i++);
[/code]

Posted: Thu Jan 24, 2008 8:24 am
by AJ
Hi,

Most likely it's the first option - something is assuming zeroed memory. For example, if you are paging, you should really zero each new page table / directory before using them and as ucosty mentioned, do not use any variable uninitialised.

The wait for I/O will depend on what device you are talking to. Some devices may need no wait at all, some may requre several ms. Some devices, you will have to do a sleep manually, some provide busy flags, so that you can keep polling the status register until the busy flag is clear.

Cheers,
Adam

Posted: Thu Jan 24, 2008 8:40 am
by AlfaOmega08
I'm not currently using paging...

For the I/O i'm handling only the keyboard. I know I've to test the bit1 of the port 0x64 before write. But in my case, it seems the problem is before the initialization of the drivers.

The problem is immediately after the boot code. The first thing my kernel does is a ClearScreen. And it crashes before that

Posted: Thu Jan 24, 2008 8:47 am
by ucosty
What boot code are you using?

Posted: Thu Jan 24, 2008 8:51 am
by AJ
Suggestion: Run it on VPC and have COM1 output to a text file. Write a really basic serial driver which does not use your normal driver interface (just have it compiled directly in, with a com_putc() function which can be called from anywhere in your kernel) and at certain points just output 'A', 'B', 'C', etc...

This will really quickly enable you to establish the site of the crash. I have always found it useful in my test kernels to automatically echo all console output to a COM port by default.

Cheers,
Adam

Posted: Thu Jan 24, 2008 9:22 am
by ucosty
AJ wrote:This will really quickly enable you to establish the site of the crash. I have always found it useful in my test kernels to automatically echo all console output to a COM port by default.
My OS does that and it works nicely. I still have no idea, however, how I got it in my head that it would be a good idea to test the serial output by printing it to the console though. :x

Posted: Thu Jan 24, 2008 9:35 am
by Solar
One such problem I heard about is that Bochs emulated floppy never fails, while a "real" floppy drive can fail numerous times before getting it right.

I never got to the point of floppy access, perhaps one of the others could pitch in details.

Posted: Thu Jan 24, 2008 9:43 am
by AlfaOmega08
I've writed my boot code by myself. It loads a KERNEL_SIZE number of sectors in the memory at 0x10000, disable ints, enable A20, load gdt, switch to PMode and jmp to 0x10000

Code: Select all

KERNEL_SIZE	EQU	50

[BITS	16]
[ORG	7C00h]

XOR	AX, AX
MOV	SP, 7C00h
MOV	BP, 7C00h

MOV	SI, KERNEL_SIZE
XOR	BX, BX
MOV	AX, 1000h
MOV	ES, AX
MOV	CX, 2
XOR	DX, DX

Again:
	MOV	AH, 2
	MOV	AL, 1
	INT	13h
	JC	Error

	PUSH	AX
	PUSH	BX
	MOV	AH, 0Eh
	MOV	AL, '.'
	MOV	BX, 7
	INT	10h
	POP	BX
	POP	AX

	MOV	AX, ES
	ADD	AX, 32
	MOV	ES, AX

	DEC	SI
	JZ	Readed

	INC	CX
	CMP	CL, 18
	JBE	Again

	MOV	CL, 1
	INC	DH
	CMP	DH, 2
	JNE	Again

	MOV	DH, 0
	INC	CH
	JMP	Again

Error:
	MOV	AH, 0Eh
	MOV	AL, 'E'
	MOV	BX, 7
	INT	10h
	XOR	AX, AX
	INT	16h
	INT	19h

Readed:
	MOV	DX, 3F2h
	MOV	AL, 0Ch
	OUT	DX, AL

CLI
MOV	AL, 8Dh
OUT	70h, AL
IN	AL, 71h

Wait1:
	IN	AL, 64h
	TEST	AL, 2
	JNZ	Wait1

	MOV	AL, 0D1h
	OUT	64h, AL

Wait2:
	IN	AL, 64h
	TEST	AL, 2
	JNZ	Wait2

	MOV	AL, 0DFh
	OUT	60h, AL

LGDT	[GDTR]

MOV	EAX, CR0
OR	AL, 1
MOV	CR0, EAX

JMP	08h:Main32

Main32:
[BITS	32]
	MOV	EAX, 10H
	MOV	DS, AX
	MOV	ES, AX
	MOV	FS, AX
	MOV	GS, AX
	MOV	SS, AX

	MOV	ESP, 900000h

	PUSH	DWORD 2
	POPFD

	MOV	EAX, 10000h

	JMP	EAX

	CLI
	HLT

[BITS	16]
GDT:
NullSegment:
	DD	0
	DD	0

CodeSegment:
	DW	0FFFFh
	DW	0
	DB	0
	DB	9Ah
	DB	0CFh
	DB	0

DataSegment:
	DW	0FFFFH
	DW	0
	DB	0
	DB	92h
	DB	0CFh
	DB	0

GDTEnd:

GDTR:
	DW	GDTEnd - GDT - 1
	DD	GDT

[BITS	32]

times (510 - ($ - $$))	DB	0
DW	0AA55h

Posted: Wed Feb 06, 2008 12:50 pm
by AlfaOmega08
I've tried to rewrite my bootloader (now with FAT12 support :D ), and I forgot to put the code to enable the A20 Gate. It has worked wonderful...
As I have put the A20 Gate enabling, it has started crash.

I can say that the bootloader crashes on the jump to the kernel, because commenting that line, it does not crash any more.

I enable A20 with this code:

Code: Select all

	CALL	Empty8042
	MOV	AL, 0D1h
	OUT	64h, AL
	CALL	Empty8042
	MOV	AL, 0DFh
	OUT	60h, AL
	CALL	Empty8042
Where "Empty8042" is:

Code: Select all

Empty8042:
	IN	AL, 64h
	TEST	AL, 2
	JNZ	Empty8042
	RET

And this is my PMode entry point:

Code: Select all

[BITS	32]
Main32:
	MOV	AX, 10h
	MOV	DS, AX
	MOV	ES, AX
	MOV	FS, AX
	MOV	GS, AX
	MOV	SS, AX
	MOV	ESP, 90000h

	MOV	EAX, 100000h
	JMP	EAX   ;If I comment this, it doesn't crash

	CLI
	HLT

Posted: Thu Feb 07, 2008 9:29 am
by AlfaOmega08
Can anyone help me?

Posted: Thu Feb 07, 2008 9:39 am
by Combuster
For starters, use brendan's bios and configure it to fill memory with garbage. Hopefully that will make the error appear in bochs as well.

Posted: Thu Feb 07, 2008 1:51 pm
by AlfaOmega08
I've not found brendan's bios, neither on google...
Anytime, now the problem is on VPC not on bochs...

I've modified my code for the A20 Gate according to the brokenthorn one. The routine to enable the A20 returns -1. As whe cannot enable A20 with keyboard.
This explain why it doesn't jump... the address is over 1 MB!

Can I starts my kernel in real mode, write routines in C for loading GDT, enabling A20 (trying with keyboard, then INT 15, ...), and switch to PMode? Does gcc support real mode?

Posted: Thu Feb 07, 2008 4:46 pm
by Masterkiller
You could try to enable A20 trough the system control port A (port 0x92). It is faster and easier (you don't have to wait).
The other thing that you could do is to write handle for 'double fault' exception to display somthing on screen. That will explain much :)
The code you posted does not change the DS and SS register in real-mode. LGDT format gets the address from the DS:immediate. Try to debug on bochs to see where system restarts and is the GDT is properly loaded.