Page 1 of 1

Another bootloader problem

Posted: Fri Jan 30, 2015 5:27 pm
by Techel
Recently i used int 13h function 2 to load my kernel. I passed the bootdrive, start sector 2, destination buffer 0000:0800 and my kernel has been loaded.
Since my kernel gets bigger and the bios can only load up to 63 (~31KiB) sectors at once, I considered the following function:

Code: Select all


mov ax, 0x0000
mov es, ax
mov bx, 0x8000
mov ax, 1
mov cl, 80 ;load 80 sectors (40KiB)
call ReadSectors
jc .error
jmp 0x0000:0x8000

;...

;;es: buffer segment, bx: buffer offset, ax: start sector, cl: num sectors
ReadSectors:
	mov byte[.remainsec], cl
	push ax
	push bx
	push es
	
	mov ah, 8 ;get sectors per track
	mov dl,[bootdrive]
	int 13h
	and cl, 0x3F
	
	pop es
	pop bx
	pop ax
	
	mov byte[.secpertrack], cl
	div cl
	mov byte[.currcylinder], al ;startcylinder = absolute sector/sectors per track
	mov byte[.currsector], ah ;startsector = absolute sector % sectors per track
   .readsectors:
		mov al, 1 ;;read one sector	   
		mov ch, byte[.currcylinder] ;cylinder
		mov cl, byte[.currsector] ;sector
		inc cl ;sector count starts at 1
		mov dh, 0 ;head = 0
		mov ah, 2 ;function "read"
		mov dl,[bootdrive]
		int 0x13
		jnc .success
		
		stc
		ret ;;failure
		
	   .success:
		inc byte[.currsector] ;inc sector
		mov al, byte[.secpertrack]
		cmp byte[.currsector], al
		jb .nowrap ;if greater than sectors per track, increment track and set sector to 0
			mov byte[.currsector], 0
			inc byte[.currcylinder]
	   .nowrap:
	   
		dec byte[.remainsec] ;decrement sector count
		jz .end
		
		mov ax, es ;add 512 to buffer pointer
		add ax, 0x20 ;512 >> 4
		mov es, ax
		jmp .readsectors
		
	.end:
		clc
		ret
		
	.secpertrack db 0
	.currsector db 0
	.currcylinder db 0
	.remainsec db 0
But the problem is that it does not work :lol:
I've debugged a lot using Bochs. It seems that the first sectors are loaded properly and the second stage loader is executed. But at some point the CPU runs into invalid code. (My kernel is definitely working with the mentioned method above).

For those who want to know: The stack is set up correctly (0000:7C00) and the start sector passed to int 13h/2 is counted from 1.


My kernel image without the 512-byte bootloader is 28KiB in size and inserted into Bochs as a 1.44M floppy.
An interesting point is that in the Bochs-Logfile it say 44 times 'read() on floppy image returns 0', so only 36 sectors, 18KiB get loaded from the file into memory.

Re: Another bootloader problem

Posted: Fri Jan 30, 2015 7:56 pm
by Techel
Ok, i think the problem is the CHS conversion.

Re: Another bootloader problem

Posted: Sat Jan 31, 2015 8:22 am
by Techel
Ok, problem solved, there was some trouble with CHS :wink:
Here is the corrected version:

Code: Select all

;;es: buffer segment, bx: buffer offset, ax: start sector, cl: num sectors
ReadSectors:
	mov byte[.remainsec], cl
	
	push es
	push ax
	push bx

	mov ah, 8 ;get sectors per track
	mov dl,[bootdrive]
	int 13h
	and cl, 0x3F
	mov byte[.secpertrack], cl
	inc dh
	mov byte[.numheads], dh
	
	pop bx
	pop ax
	pop es
	
	xor dx, dx ;convert LBA to CHS
	xor ch, ch
	mov cl, byte[.secpertrack]
	div cx
	mov byte[.currsector], dl
	xor dx, dx
	mov cl, byte[.currsector]
	div cx
	mov byte[.currhead], dl
	mov byte[.currcylinder], al
   .readsectors:
		mov ch, byte[.currcylinder] ;cylinder
		mov cl, byte[.currsector] ;sector
		inc cl ;sector count starts at 1
		mov dh, byte[.currhead];head
		mov dl,[bootdrive]
		mov al, 1 ;;read one sector
		mov ah, 2 ;function "read"
		int 0x13
		jnc .success
		
		stc
		ret ;;failure
		
	   .success:		
		inc byte[.currsector]
		mov al, byte[.secpertrack]
		cmp byte[.currsector], al
		jb .nowrap
			mov byte[.currsector], 0
			inc byte[.currhead]
			mov al, byte[.numheads]
			cmp byte[.currhead], al
			jb .nowrap
				mov byte[.currhead], 0
				inc byte[.currcylinder]
	   .nowrap:
	   
		dec byte[.remainsec] ;decrement sector count
		jz .end
		
		mov ax, es ;add 512 to buffer pointer
		add ax, 0x20 ;512 >> 4
		mov es, ax
		jmp .readsectors
		
	.end:
		clc
		ret
		
	.secpertrack db 0
	.numheads db 0
	.currsector db 0
	.currcylinder db 0
	.currhead db 0
	.remainsec db 0