Page 1 of 1

Strange error

Posted: Sat Sep 04, 2010 10:31 am
by Karlosoft

Code: Select all

	%include "gdt.inc"

	struc	BB		;FAT Boot block
		resb	0xD	;Things we ignore
BB_clu		resb	1	;Sectors per cluster
BB_res		resw	1	;Reserved sectors
BB_fats		resb	1	;Number of FATs
BB_root		resw	1	;Root directory entries
		resb	3	;Things we ignore
BB_fat		resw	1	;Sectors per fat
BB_sec		resw	1	;Sectors per track
BB_head		resw	1	;Heads
	endstruc

 [bits 16]


;>   cs = 0
;>>  dl = drive we were booted from

boot:	jmp short start			;Standard start of boot sector
	nop
	resb	0x3B			;Skip over parameters (set by format)

start:					;{0}

	mov ax,0
	mov ds, ax
	mov es, ax
	mov ss, ax

	mov bl,00h
	mov ax,1112h
	int 10h


	mov ax,1003h
	int 10h

	mov ax,0x4f00
	mov bx,0
	mov es,bx
	mov di,500h
	int 10h

	cli



	lgdt	[cs:gdt]		;Load GDT
	mov	ecx, CR0		;Switch to protected mode
	inc	cx
	mov	CR0, ecx		;{5}
.5:	in	al, 0x64		;Enable A20 {4A}
	test	al, 2
	jnz	.5
	mov	al, 0xD1
	out	0x64, al
.6:	in	al, 0x64
	and	ax, byte 2
	jnz	.6
	mov	al, 0xDF
	out	0x60, al


;>   ah = 0
;>   dl = drive we were booted from

	mov	al, flat_data		;Selector for 4Gb data seg
;//hereeeeeeeee
	;mov	ds, ax			;{2} Extend limit for ds

	;mov	es, ax			;Extend limit for es

	dec	cx			;Switch back to real mode

	mov	CR0, ecx		;{5}

	mov	[boot], dl		;Save drive number we came from
	mov	sp, 0x800		;{1B}

	xor	eax, eax		;Segment
	mov	ds, ax			;
	mov	ss, ax
	mov	es, sp			;Read directory at 800:0 {1C}



;>   eax = 00000000

	mov	al, [boot+BB_fats]	;Number of FATs
	mul	byte [boot+BB_fat]	;Times size of FAT
	add	ax, [boot+BB_res]	;Plus Sectors before first FAT
					;eax = LBN of Root directory
	movzx	edi,word [boot+BB_root]	;Root directory entries
	push	di			; used again later
	dec	di			;Convert to number of sectors
	shr	di, 4			;  16 directory entries per sector
	inc	di
	call	read_sectors

;>  eax  = LBN of root directory
;>  edi  = length of root directory in sectors
;>  [sp] = length of root directory in entries
;>  esi  = 00000000

	lea	ebp, [eax+edi]		;ebp = LBN of cluster 2

	pop	bx			;Root directory entries
	xor	di, di			;Point at directory {1C}
.20:	mov	si, file_name		;Name of file we want
	xor	ecx, ecx
	mov	cl, 11
	a32 rep cmpsb			;Found the file?
	je	found			;Yes
	add	cl, 21			;Offset to next directory entry
	add	edi, ecx		;Advance to next entry
	dec	bx			;Loop through all entries
	jnz	.20

	;Couldn't find file in directory
boot_error:
disk_error:	
	mov	ax, 0xE07		;{3}
	int	10h
	jmp short $

;>> ecx   = 00000000
;> es     = 800
;> es:edi = Directory entry of file
;> ebp    = LBN of cluster 2
;> eax    = 0000????

found:	push	word [es:edi+0xF]	;Starting cluster of file
	mov	di, [boot+BB_fat]	;Size of FAT (in sectors)
	mov	ax, [boot+BB_res]	;LBN of FAT
	call	read_sectors

	mov	bx, 0x4000
	mov	es, bx			;es = 0x4000
	mov	edi, 0x100000-0x40000	;{1D}{4B} One megabyte minus ES base
.10:

;>>    ecx = 0000????
;>    [sp] = Next cluster of file
;>     esi = 0000????
;>>    edx = 0000????
;>  es:edi = Destination address
;>     ebp = LBN of cluster 2
;>      ds = 0

	xor	eax, eax
	pop	si			;Next cluster of file
	mov	bx, si
	cmp	si, 0xFF8		;Valid cluster?
	jae	eof			;No: assume end of file
					;Yes: (c-bit set)
	rcr	bx, 1			;bx = 0x8000 + cluster/2
	mov	bx, [bx+si]		;Get word containing FAT entry
	jnc	.11			;Entry is low 12 bits
	shr	bx, 4			;Entry was high 12 bits
.11:	and	bh, 0xF			;Mask to just 12 bits
	push	bx			;Save cluster after next
	push	di			;Save destination address {7}
	mov	al, [boot+BB_clu]	;Size of each cluster
	mov	di, ax			;  (in sectors)
	dec	si
	dec	si
	mul	esi			;Times cluster number minus 2
	add	eax, ebp		;Plus LBN of cluster 2	
	call	read_sectors		;Read that cluster

;>     ecx = 0000????
;>>    edx = 0000????
;>      di = Clustersize in sectors
;>     esi = 0
;>>    ebp = LBN of cluster 2
;>    [sp] = Bottom 16-bits of destination address {7}
;>> [sp+2] = Following cluster
;>      ds = 0
;>      es = 4000

	mov	cx, di			;Cluster size in sectors
	xchg	ch, cl			;Cluster size in words
	pop	di			;Restore destination address {7}
	es a32 rep movsw
	jmp short .10			;Loop until end of file

;>     eax = 0
;>     edx = 0000????
;>      bx = 0FF?

eof:
	mov	dx, 0x9C00
	mov	es, dx			;es = 9C00
	xor	di, di			;{1E} Address of page tables WRT es
	mov	dh, 4096/256		;edx = 4096
.10:	mov	cx, 1024
	mov	al, 7
.20:	stosd
	add	eax, edx
	int	8			;{8}
	loop	.20
	shr	eax, 2			;{4C} (first time only) 4Mb / 4 = 1Mb
	neg	bl			;Done just one page?
	jns	.10			;Yes: do one more

	cli				;{6}

	mov	eax, 0x9C007		;First page tbl pointer in page dir
	stosd				;{1H}
	mov	ax, (1024-3)*2
	xchg	ax, cx
	rep stosw
	mov	ax, 0xD007		;0FF800000 page tbl pointer
	stosd				;{1F}
	mov	ah, 0xE0		;Page directory self pointer
	stosd				;{1G}
	mov	al, 0
	mov	CR3, eax		;Set up page directory
	mov	eax, CR0		;Turn on paging and protected mode
	or	eax, 0x80000001
	mov	CR0, eax
	mov	cl, flat_data		;Setup ds and es
	push	cx			;{5}
	pop	ds
	mov	es, cx
	jmp dword 8:0xFF800000		;Go
	
read_sectors:
; Input:
;	EAX = LBN
;	DI  = sector count
;	ES = segment
; Output:
;	EBX high half cleared
;	DL = drive #
;	EDX high half cleared
;	ESI = 0
; Clobbered:
;	BX, CX, DH

	push	eax
	push	di
	push	es

.10:	push	eax		;LBN

	cdq			;edx = 0
	movzx	ebx, byte [boot+BB_sec]
	div	ebx		;EAX=track ;EDX=sector-1
	mov	cx, dx		;CL=sector-1 ;CH=0
	sub	bl, dl		;BX = max transfer before end of track
	cmp	di, bx		;Do we want more than that?
	ja	.20		;Yes, do just this much now
	mov	bx, di		;No, do it all now
.20:	mov	esi, ebx	;Save count for this transfer.

	inc	cx		;CL=Sector number
	xor	dx, dx
	mov	bl, [boot+BB_head]
	div	ebx		;EAX=cylinder ;EDX=head

	mov	dh, dl		;Head
	mov	dl, [boot]	;Drive
	xchg	ch, al		;CH=Low 8 bits of cylinder number; AL=0
	shr	ax, 2		;AL[6:7]=High two bits of cylinder
	or	cl, al		;CX = Cylinder and sector

	mov	ax, si		;Sector count
	mov	ah, 2		;Read
	xor	bx, bx
	push	ax
	int	13h
	pop	ax
	jnc	.30

	int	13h		;If at second you don't succeed, give up
	jc near	disk_error

.30:	pop	eax
	add	eax, esi	;Advance LBN

	push	si
	shl	si, 5
	mov	bx, es
	add	bx, si		;Advance segment
	mov	es, bx
	pop	si

	sub	di, si
	ja	.10

	pop	es
	pop	di
	pop	eax
	xor	si, si
	ret	

file_name db 'KERNEL  BIN'

gdt	start_gdt		;{9}

flat_code	desc	0, 0xFFBFF, D_CODE+D_READ+D_BIG+D_BIG_LIM

flat_data	desc	0, 0xFFFFF, D_DATA+D_WRITE+D_BIG+D_BIG_LIM

	end_gdt

	db	0x55, 0xAA		;Standard end of boot sector

This is the code of a 16bit loader based on bootf2 bootloader... When it works like a bootloader all is good, but when I load it as module with an other and I run it, when it reach the instruction mov ds,ax it reboot.

Any idea?

Ps. The bootloader which loads it left the real mode enabled.

Re: Strange error

Posted: Sat Sep 04, 2010 3:17 pm
by gerryg400

Code: Select all

   mov   al, flat_data      ;Selector for 4Gb data seg
;//hereeeeeeeee
   ;mov   ds, ax         ;{2} Extend limit for ds
Shouldn't you load ax with flat_data ? What is in ah at this point ?

Re: Strange error

Posted: Sat Sep 04, 2010 4:24 pm
by Karlosoft
It still doesn't work :(

Re: Strange error

Posted: Sat Sep 04, 2010 4:31 pm
by gerryg400
It still doesn't work
Does it crash at exactly the same place ?

Oh, please show us gdt.inc

Re: Strange error

Posted: Sat Sep 04, 2010 6:38 pm
by Karlosoft
Yes, always in the same point.

http://wiki.osdev.org/Bootf

You can download the gdt.inc and all the other code from that link. IThe code is so long to post here that will be not easy readable ;)

Re: Strange error

Posted: Sat Sep 04, 2010 7:16 pm
by gerryg400
The code assumes cs == ds == 0. Maybe it's not equal when loaded as a module.

Re: Strange error

Posted: Sun Sep 05, 2010 2:16 am
by Karlosoft

Code: Select all

   mov ax,0
   mov ds, ax
   mov es, ax
   mov ss, ax
I set the register before everything. CS is not set but the module loader jumps up to 0:7c00, the new location where the module is written.

Re: Strange error

Posted: Sun Sep 05, 2010 2:40 am
by kmtdk
Hi karlosoft :P
well after a few secounds of studying your code, ( i didn't read all the macro pars ...) but if i get it right, the problem is the loading of the GDT
first, you load the LGDT [CS:GDT]
but GDT is set as "start_gdt" , where GDT should be "end_gdt - start_gdt -1", and the next dword should then be the start of the gdt.
next, you load al with flat_data, but it is supossed to be 0x08 ( but since you just used the label, it is going to use the adress... )
and just for clearity, set ah =0 , dont assume.

... and you have to jump into protected mode, at least that worked for me.


be aware, im not sure, but returning from protected mode is that simple, but rembering myself have some trouble about it.

KMT_dk

Re: Strange error

Posted: Sun Sep 05, 2010 3:44 am
by gerryg400
... and you have to jump into protected mode, at least that worked for me.
This might be important. The manuals say you should do a jmp after going into protected mode to prevent random problems. It's usually not necessary but you never know. A near jmp is better because you'll remain in 16 bit mode.

Re: Strange error

Posted: Sun Sep 05, 2010 5:43 am
by kmtdk
well, since you know where the error happend i guess you have used an emulator. I just tested the part (but without chainloading), and setting the registeres to random thins ( except cs) which i might assume, is the only register you need to take a look on thoughout the code. but there is only one explantion, and that is, when you load the part, you have magical change either the adress, or CS.

KMT DK

Re: Strange error

Posted: Sun Sep 05, 2010 5:49 am
by gerryg400
Where's the stack pointer ? It doesn't look like your setting it so maybe when you do your int 10 you're trashing something.

Re: Strange error

Posted: Sat Sep 11, 2010 6:46 am
by Karlosoft
Thank you everybody! There wasn't any misake in the code. The stage2 of the bootloader was just a little bugged -.-