BIOS int 13 issues

Question about which tools to use, bugs, the best way to implement a function, etc should go here. Don't forget to see if your question is answered in the wiki first! When in doubt post here.
Post Reply
AndyB
Posts: 15
Joined: Fri Dec 17, 2010 5:43 pm

BIOS int 13 issues

Post by AndyB »

Hi, I have been working on implementing FAT 32 support in my VBR.
Unfortunately I cant seem to get BIOS int 13h to work, I have tried many implementations including AH=02h but they always seem to fail.

Obviously I must be doing something seriously wrong. At first after switching to int 13h extensions, I wasnt checking if they were available, but I have added a check now and it always seems to say that the extensions are not available (Bochs, Qemu and Virtual Box).

I have spent many hours on this and I am hoping someone here could shed some light on the problem.

I also note that wikipedia states that the default DL value for a HDD is 0x80, but on Qemu and Bochs DL is 0x00 at boot. I have tried manually setting dl to 0x80 but still no luck.

Code: Select all

bits	16							; We are still in 16 bit Real Mode
org		0x7c00						; We are loaded by BIOS at 0x7C00

start:
	jmp entry

	BPBOEM_ID				db		"GRAVITY "
	BPBBytesPerSector		dw		0x0200
	BPBSectorsPerCluster	db		0x08
	BPBReservedSectors		dw		0x0020
	BPBTotalFATs			db		0x02
	BPBMaxRootEntries		dw		0x0000
	BPBNumberOfSectors		dw		0x0000
	BPBMediaDescriptor		db		0xF8
	BPBSectorsPerFAT		dw		0x0000
	BPBSectorsPerTrack		dw		0x0000
	BPBSectorsPerHead		dw		0x0000
	BPBHiddenSectors		dd		0x00000000
	BPBTotalSectors			dd		0x00000000		
	BPBBigSectorsPerFAT		dd		0x00000000
	BPBFlags				dw		0x0000
	BPBFSVersion			dw		0x0000
	BPBRootDirectoryStart	dd		0x00000002
	BPBFSInfoSector			dw		0x0001
	BPBBackupBootSector		dw		0x0006
	
	times 13 db 0 ; jmp next offset

	BPBDriveNumber			db 		0x00
	BPBSignature			db 		0x29
	BPBVolumeID				dd 		0xFFFFFFFF
	BPBVolumeLabel			db 		"Gravity Vol"
	BPBSystemID				db 		"FAT32   "

entry:
	cli				; clear interrupts
	xor	ax, ax			; null segments
	mov	ds, ax
	mov	es, ax
	mov	ax, 0x0			; stack begins at 0x9000-0xffff
	mov	ss, ax
	mov	sp, 0xFFFF
	sti				; enable interrupts
	
	mov dl, 0x80
	mov al, dl
	call printb
	; Print Entry Message
	mov	si, msg_init
	call	PrintString	

	; Check Int 13H Extensions Available
	mov ah,0x41			;INT 13h AH=41h: Check Extensions Present	
	mov bx,0xAA55			;Must be AA55
	int 0x13			;Check extensions
	jc  BootNoExt			;Carry flag set, No extensions
	cmp bx,0x55AA			;Is BX 55AA
	jnz BootNoExt			;Nope, No extensions

	; Load one sector starting at 0x01 to 0x8000
	mov eax, 0x0001
	mov di, 0x8000
	mov cx, 0x01
	call Fat32_Read_Disk
	jc BootError
	
	; Print Exit Message
	mov	si, msg_exit
	call	PrintString
	jmp halt
	
;
; Subroutines
;

;Read_Disk - Reads sectors form disk
;In : EDX:EAX = QWORD LBA on disk to read from
;	  ES:DI => Location in memory to read to
;	  CX = Number of sectors to read
;Out: Carry on error
Fat32_Read_Disk: 						
	pushad									;Save registers
	mov DWORD [DAP_LBA_MSD],edx				;EDX = MSD of LBA
	mov DWORD [DAP_LBA_LSD],eax				;EAX = LSD of LBA
	mov WORD [DAP_Segment],es				;ES = Segment
	mov WORD [DAP_Offset],di				;DI = Offset
	mov WORD [DAP_Sectors],cx				;CX = Sectors
	mov cx,0x05								;Attempt to read disk 5 times
Fat32_Read:
	mov ax,0x4200							;INT 13h AH=42h: Extended Read Sectors From Drive
	mov dl,BYTE [BPBDriveNumber]				;DL = Drive Number
	lea si,[DAP_Size]						;SI = Offset if DAP
	int 0x13								;Read disk
	jnc Fat32_Read_Success						;Carry clear? Return

	dec cx									;Read_count--
	or cx,cx								;Read_count=0?
	jz Fat32_Read_Error							;Return w/ carry
	
	xor ah,ah								;INT 13h AH=00h: Reset Disk Drive
	int 0x13								;Reset Disk
	jc Fat32_Read_Error							;Carry Flag? error
	jmp Fat32_Read								;Attempt to read disk again
Fat32_Read_Error:
	stc										;Set the carry flag to indicate failure
Fat32_Read_Success:
	popad									;Get Registers back
	ret										;Return

BootError:
	mov si, msg_error
	call PrintString
BootNoExt:
	mov si, msg_noext
	call PrintString

halt:
	cli							; Clear all Interrupts
	hlt							; halt the system

;
;	Includes
;
;%include 'asm/printstring.asm'
;%include 'asm/printhex.asm'
;Including file source for post
;*************************
;	Print Functions
;*************************
PrintString:
	lodsb
	or	al, al		; Al=cur char
	jz	PrintDone	; If null..bail
	mov	ah, 0x0E	; Next char
	int	0x10		; Print
	jmp	PrintString		; Loop
PrintDone:
	mov ax, 0E0Dh
	xor bx, bx
	int 10h
	mov al, 0Ah
	int 10h
	ret

;
;	Variables
;
DAP_Size			db 0x10					;Size of packet, always 16 BYTES
DAP_Reserved		db 0x00					;Reserved
DAP_Sectors			dw 0x0000				;Number of sectors to read
DAP_Offset			dw 0x0000				;Offset to read data to
DAP_Segment 		dw 0x0000				;Segment to read data to
DAP_LBA_LSD			dd 0x00000000			;QWORD with LBA of where to start reading from
DAP_LBA_MSD			dd 0x00000000	

;
;	String Messages
;
msg_init		db	"[VBR] Init", 0
msg_exit		db	"[VBR] Exit", 0
msg_error		db	"[VBR] Boot Error!", 0
msg_noext		db	"[VBR] Not Ext int 13h!", 0

times 510 - ($-$$) db 0

dw 0xAA55

Can anyone see why this would fail?

Many thanks,
Andrew
User avatar
DavidCooper
Member
Member
Posts: 1150
Joined: Wed Oct 27, 2010 4:53 pm
Location: Scotland

Re: BIOS int 13 issues

Post by DavidCooper »

mov ax, 0x0 ; stack begins at 0x9000-0xffff
mov ss, ax
mov sp, 0xFFFF
Stack misaligned - as it is, it'll write to FFFD and FFFE the first time it's used because it always writes immediately below the byte SP is pointing at. You want to set it to 0x0 (I think it'll wrap around without any problems - if in doubt, set it to 7C00 to let it run down from imediately under your boot sector).
mov dl, 0x80
mov al, dl
Don't set DL this way - use the value that was passed to you in DL by the BIOS when it handed control to your boot sector as it will be the correct value for the drive it's booting from.
; Check Int 13H Extensions Available
mov ah,0x41 ;INT 13h AH=41h: Check Extensions Present
mov bx,0xAA55 ;Must be AA55
int 0x13 ;Check extensions
jc BootNoExt ;Carry flag set, No extensions
cmp bx,0x55AA ;Is BX 55AA
jnz BootNoExt ;Nope, No extensions
Try using 0x55AA in BX before calling int 0x13 - you've used the boot sig instead.

Code: Select all

   ; Load one sector starting at 0x01 to 0x8000
   mov eax, 0x0001
   mov di, 0x8000
   mov cx, 0x01
   call Fat32_Read_Disk
   jc BootError
   
...

;Read_Disk - Reads sectors form disk
;In : EDX:EAX = QWORD LBA on disk to read from
;     ES:DI => Location in memory to read to
;     CX = Number of sectors to read
;Out: Carry on error
Fat32_Read_Disk:                   
   pushad                           ;Save registers
   mov DWORD [DAP_LBA_MSD],edx            ;EDX = MSD of LBA
   mov DWORD [DAP_LBA_LSD],eax            ;EAX = LSD of LBA
   mov WORD [DAP_Segment],es            ;ES = Segment
   mov WORD [DAP_Offset],di            ;DI = Offset
   mov WORD [DAP_Sectors],cx            ;CX = Sectors
   mov cx,0x05                        ;Attempt to read disk 5 times
Fat32_Read:
   mov ax,0x4200                     ;INT 13h AH=42h: Extended Read Sectors From Drive
   mov dl,BYTE [BPBDriveNumber]            ;DL = Drive Number
   lea si,[DAP_Size]                  ;SI = Offset if DAP
   int 0x13                        ;Read disk
   jnc Fat32_Read_Success                  ;Carry clear? Return
You have no idea what's in EDX when you copy it into the DAP because you haven't set it to anything (other than the drive number earlier, though that'll have been corrupted later by calling the BIOS to print to the screen, which is another reason why your check for extensions may fail). There may well be other problems - I'll have another look later if it still doesn't work.

Edit: just spotted this:-
BPBDriveNumber db 0x00
and this:-
mov dl,BYTE [BPBDriveNumber] ;DL = Drive Number
If the BIOS doesn't patch the right drive number into your BPB you're stuffed - you need to store DL to that variable in the BPB early on yourself as the BIOS will certainly put the right drive number in DL for you.
Help the people of Laos by liking - https://www.facebook.com/TheSBInitiative/?ref=py_c

MSB-OS: http://www.magicschoolbook.com/computing/os-project - direct machine code programming
egos
Member
Member
Posts: 612
Joined: Fri Nov 16, 2007 1:59 pm

Re: BIOS int 13 issues

Post by egos »

AndyB wrote:Obviously I must be doing something seriously wrong. At first after switching to int 13h extensions, I wasnt checking if they were available, but I have added a check now and it always seems to say that the extensions are not available (Bochs, Qemu and Virtual Box).
Be considerate.

Code: Select all

        mov bx,55AAh <--
        mov ah,41h
        push dx
        int 13h
        pop dx
        jc short @f
        cmp bx,0AA55h <--
        jne short @f
        shr cx,1
        jc short ok
@@:
        ; no edd
ok:
I have spent many hours on this and I am hoping someone here could shed some light on the problem.
You neglect saving register values for later use before calling BIOS functions. It can be a problem.
I also note that wikipedia states that the default DL value for a HDD is 0x80, but on Qemu and Bochs DL is 0x00 at boot.
It's not true.
If you have seen bad English in my words, tell me what's wrong, please.
AndyB
Posts: 15
Joined: Fri Dec 17, 2010 5:43 pm

Re: BIOS int 13 issues

Post by AndyB »

mov ax, 0x0 ; stack begins at 0x9000-0xffff
mov ss, ax
mov sp, 0xFFFF
Stack misaligned - as it is, it'll write to FFFD and FFFE the first time it's used because it always writes immediately below the byte SP is pointing at. You want to set it to 0x0 (I think it'll wrap around without any problems - if in doubt, set it to 7C00 to let it run down from imediately under your boot sector).
Ah ok, I have now set the stack to 0x7C00
mov dl, 0x80
mov al, dl
Don't set DL this way - use the value that was passed to you in DL by the BIOS when it handed control to your boot sector as it will be the correct value for the drive it's booting from.
As mentioned in my original post, I had just tried manually setting DL after I couldnt get anything else to work. I thought that I had removed it before posting the above code, apologies.
With this though and:
I also note that wikipedia states that the default DL value for a HDD is 0x80, but on Qemu and Bochs DL is 0x00 at boot.
It's not true.[/quote]
My MBR saves the DL and than passes it to the VBR but it was being trashed before being passed to the VBR. (By patching the BPB Drive Number value). Fixed now.
You have no idea what's in EDX when you copy it into the DAP because you haven't set it to anything (other than the drive number earlier, though that'll have been corrupted later by calling the BIOS to print to the screen, which is another reason why your check for extensions may fail). There may well be other problems - I'll have another look later if it still doesn't work.
by setting EDX properly I have managed to successfully load sectors into memory.

As for using the boot sig AA55 instead of 55AA, i wouldnt have spotted that one, thank you for your keen eyes!

Many thanks to both of you for your advice,
Andrew
Post Reply