BIOS int13h function 42h problem

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
FlashBurn
Member
Member
Posts: 313
Joined: Fri Oct 20, 2006 10:14 am

BIOS int13h function 42h problem

Post by FlashBurn »

I´ve written my own MBR and bootsector code. Both are working, but not on all PCs :(

The problem I have is that my bootsector code doesn´t work on all PCs I tested my code on. The observation I made is, that it seems that server boards don´t like my bootsector code. At the moment I´m testing on an Opteron (Socket 940) board with an AMI BIOS (it could also be that AMI BIOS is the problem, but I don´t really know).

Both, the MBR and the bootsector use funtion 42h to load sectors from disk, but I only have problems with my bootsector. The error code I get is "1" i.e. "invalid function in AH or invalid parameter".

My question now is, does anyone know what the problem could be? For me it makes no sense that it works on most PCs, but not on all (servers or AMI BIOS).
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: BIOS int13h function 42h problem

Post by gerryg400 »

FlashBurn wrote:I´ve written my own MBR and bootsector code. Both are working, but not on all PCs :(

The problem I have is that my bootsector code doesn´t work on all PCs I tested my code on. The observation I made is, that it seems that server boards don´t like my bootsector code. At the moment I´m testing on an Opteron (Socket 940) board with an AMI BIOS (it could also be that AMI BIOS is the problem, but I don´t really know).

Both, the MBR and the bootsector use funtion 42h to load sectors from disk, but I only have problems with my bootsector. The error code I get is "1" i.e. "invalid function in AH or invalid parameter".

My question now is, does anyone know what the problem could be? For me it makes no sense that it works on most PCs, but not on all (servers or AMI BIOS).
I think you may be focusing on the wrong part of your test result. Instead of asking why your bootsector works with some bioses and not others, first ask why one of your programs works and not the other. The logical first conclusion is that you have a bug in your bootsector. Is it possible you could attach the 2 programs for review ?
If a trainstation is where trains stop, what is a workstation ?
egos
Member
Member
Posts: 612
Joined: Fri Nov 16, 2007 1:59 pm

Re: BIOS int13h function 42h problem

Post by egos »

You must use function 02h if function 42h is not supported for the drive. Most modern boot loaders do this for compatibility reasons.
If you have seen bad English in my words, tell me what's wrong, please.
FlashBurn
Member
Member
Posts: 313
Joined: Fri Oct 20, 2006 10:14 am

Re: BIOS int13h function 42h problem

Post by FlashBurn »

You must use function 02h if function 42h is not supported for the drive. Most modern boot loaders do this for compatibility reasons.
Ok, because of that I´ve written, that my MBR code is working.
Do you verify that the BIOS extensions are really present?
Same as above and yes I check this in my MBR code.
The logical first conclusion is that you have a bug in your bootsector.
I´ve also come to this conclusion, but it´s not so easy to debug a bootsector on x86 hardware and the point that it works most of the time doesn´t make it easier :(
Is it possible you could attach the 2 programs for review ?
Yes, but this code is not really commented

MBR code (the include file only declares a structure for an entry in the partition table):

Code: Select all

org 0

include "partition.inc"

;----------------------------
start:
	cli
	
	cld

	xor di,di
	mov ax,07c0h
	mov bx,2000h

	mov ds,ax
	mov es,bx
	mov ss,bx

	mov sp,di
	mov si,di

	sti

	mov cx,128
	rep movsd

	jmp 2000h:relocated
;----------------------------

;----------------------------
align 4
relocated:
	mov ds,bx
	mov es,sp

	mov [bootdrv],dl
;----------------------------
load_bootsector:
	mov si,1beh
	mov cx,5
;----------------------------
;	search an active partition
align 4
.loop:
	sub cx,1
	jz .end_err_active

	cmp byte[si],80h
	je .found
	
	add si,part_entry.size_t
	jmp .loop
;----------------------------
;	load the bootsector of the partition
align 4
.found:
;----------------------------
;	test if we can use the extension int13h functions
	push si
	
	mov ah,0x41
	mov bx,0x55AA
	int 0x13
	
	pop si
	
	jc .old
	
	mov eax,[si+part_entry.start_lba]
	mov [dap.lba],eax

	mov si,dap
	mov ah,42h
.loop@found@start:
	mov dl,[bootdrv]
	mov di,3
.loop@found:	
	pusha
	
	int 13h
	
	popa

	jnc .check
	
	dec di
	jnz .loop@found

	jmp .end_err_disk
;----------------------------
.old:
	mov ax,0x201
	mov dh,[si+part_entry.beg_head]
	mov cx,[si+part_entry.beg_cylsec]
	mov bx,0x7c00
	
	jmp .loop@found@start
;----------------------------
;	check the signature of the bootsector
.check:
	cmp word[es:0x7DFE],0xAA55
	jne .end_err_active
;----------------------------
	mov dl,[bootdrv]

	jmp 0000h:7c00h
;----------------------------
.end_err_disk:
	mov si,msg_err_disk

	jmp reboot
;----------------------------
.end_err_active:
	mov si,msg_err_active

	jmp reboot
;----------------------------
.end_err_os:
	mov si,msg_err_os
;----------------------------

;----------------------------
reboot:
	call print
	mov si,msg_err_reboot
	call print

	xor ax,ax
	int 16h
	int 19h
;----------------------------

;----------------------------
print:
	mov ah,0eh

.loop:
	lodsb
	
	test al,al
	jz .end
	
	int 10h
	
	jmp .loop

.end:
	ret
;----------------------------

align 4
;----------------------------
;	data

;	vars
bootdrv			db 0
dap:
	.size		db 10h
	.reserved	db 0
	.blocks		dw 1
	.offset		dw 0
	.segment	dw 0x07C0
	.lba		dd 63,0

;	msgs
msg_err_disk		db 'Could not read disk',13,10,0
msg_err_os			db 'Operating System missing',13,10,0
msg_err_active		db 'Disk not bootable',13,10,0
msg_err_reboot		db 'Press any key to reboot',0

times 510-($-$$) db 0
dw 0xAA55
And here is the bootsector (the include declares a structure for the BPB of FAT16):

Code: Select all

org 0

include "fat12_16.inc"

jmp short start
nop

BPB fat12_16_bpb

;----------------------------
align 4
start:
	cli
	
	cld
	
	xor di,di
	mov ax,0x2000
	mov bx,0x1000
	mov ds,di
	mov sp,di
	mov bp,di

	mov si,0x7c00
	mov cx,128
	
	mov ss,bx
	mov es,bx
	
	rep movsd
	
	jmp 0x1000:load_fat
;----------------------------
align 4
load_fat:
	push cs
	mov es,ax
	pop ds
	
	sti
	
	mov word[dap.size],0x1000
;	mov word[dap.offset],cx
	mov word[dap.segment],ax
;	mov dword[dap.lba+4],ecx
	
	mov [bp+BPB.BS_DrvNum],dl
;----------------------------
;	FAT start lba= BPB_ResvdSecCnt + BPB_HiddSec
	movzx eax,word[bp+BPB.BPB_ResvdSecCnt]
	mov cx,word[bp+BPB.BPB_FATSz16]
	add eax,dword[bp+BPB.BPB_HiddSec]

	push eax
.loop:
	push cx
	
	cmp cx,0x7F
	jle .do_it
	
	mov cx,0x7F
;----------------------------
;	load the FAT
.do_it:
	call load_lba
	
	pop cx
	
	sub cx,0x7F
	jle load_root_dir
	
	pop eax
	push eax
	
	add eax,0x7F
	
	push cx
	
	bsf cx,word[bp+BPB.BPB_BytsPerSec]
	mov bx,0x7F
	sub cl,4
	shl bx,cl
	add [dap.segment],bx
	
	pop cx
	
	jmp .loop
;----------------------------
load_root_dir:
;----------------------------
;	RootDirSectors= ((BPB_RootEntCnt * 32) + (BPB_BytsPerSec - 1)) / BPB_BytsPerSec
	movzx eax,word[bp+BPB.BPB_BytsPerSec]
	mov bx,word[bp+BPB.BPB_RootEntCnt]
	bsf cx,ax
	dec ax
	shl bx,5
	add ax,bx
	shr ax,cl
	
	push eax
;----------------------------
;	StartSector= BPB_ResvdSecCnt + (BPB_NumFATs * BPB_FATSz16) + BPB_HiddSec
	movzx eax,word[bp+BPB.BPB_FATSz16]
	shl ax,1
	
	pop ecx
	pop ebx
	
	add eax,ebx
	mov dx,0x50
	mov ebx,eax
	add ebx,ecx
	
	push ebx
;----------------------------
;	destination of rootdir
	mov word[dap.segment],dx
	mov es,dx
;----------------------------
;	load the rootdir
	call load_lba
;----------------------------
load_loader:
;----------------------------
	mov dx,word[bp+BPB.BPB_RootEntCnt]
	xor di,di
;----------------------------
;	search the rootdir for the loader
align 4
.loop@search_entry:
;----------------------------
;	compare the loader name with the actual entry name
	push di

	mov si,osloader_img
	mov cx,11

	rep cmpsb

	pop di

	je .loop@found_entry

	dec dx
	jnz .loop@next
;----------------------------
.err_loader:
	mov si,msg_err_loader

	jmp reboot
;----------------------------
; check next entry
align 4
.loop@next:
	add di,fat_dir_ent.size_t

	jmp .loop@search_entry
;----------------------------
;	right entry, so save the cluster
.loop@found_entry:
	pop ecx
	
	mov bx,word[es:di+fat_dir_ent.cluster]
;----------------------------
;	test if this was the last cluster
align 4
.loop@cluster:
	cmp bx,0fff8h
	jae .end
;----------------------------
;	look if the cluster is above 64KiB
	mov si,bx
	mov dx,0x2000
	shl si,1

	jnc .loop@cluster@doit

	mov dx,0x3000
;----------------------------
;	calc the lba of the actual cluster and get the new cluster
.loop@cluster@doit:
	mov fs,dx

	mov edx,ecx
	sub bx,2
	movzx cx,byte[bp+BPB.BPB_SecPerClus]
	movzx eax,bx
	bsf cx,cx
	mov bx,[fs:si]
	shl ax,cl

	add eax,edx
;----------------------------
;	load the cluster and calculate the new segment address of the next cluster
.loop@cluster@load:
	push bx
	push edx

	movzx cx,byte[bp+BPB.BPB_SecPerClus]
	call load_lba

	bsf cx,word[bp+BPB.BPB_BytsPerSec]
	movzx ax,byte[bp+BPB.BPB_SecPerClus]
;	sub cl,4
;	shl ax,cl
;	add [dap.segment],ax
	shl ax,cl
	add [dap.offset],ax
	
	pop ecx
	pop bx

	jmp .loop@cluster
;----------------------------
align 4
.end:
	mov dl,[bp+BPB.BS_DrvNum]

	jmp 0x50:0x0
;----------------------------

;----------------------------
align 4
print:
	mov ah,0eh
;----------------------------
.loop:
	lodsb
	
	test al,al
	jz .end
	
	int 10h
	
	jmp .loop
;----------------------------
.end:
	ret
;----------------------------

;----------------------------
;	Input:
;	EAX - LBA
;	CX - # of lbas 2 load
align 4
load_lba:
	mov [dap.lba],eax			;save lba to load
	mov [dap.blocks],cx			;save # of blocks 2 load

	mov si,dap
	mov ah,0x42
	mov dl,[bp+BPB.BS_DrvNum]
	int 13h

	jc .end_err
;----------------------------
.end:
	ret
;----------------------------
.end_err:
	shr ax,8
	add al,'A'
	mov ah,0x0e
	int 0x10

	mov si,msg_err_read
;----------------------------

;----------------------------
reboot:
	call print
	mov si,msg_reboot
	call print

	xor ax,ax
	int 16h
	int 19h
;----------------------------

align 4
;----------------------------
;	consts
osloader_img	db 'OSLOADER   '

;	msgs
msg_err_read	db 'Error reading disk',13,10,0
msg_err_loader	db 'OS-Loader not found',13,10,0
msg_reboot		db 'Press any key to reboot',0

times 510-($-$$) db 0
dw 0aa55h
;----------------------------
;	bss
dap:
	.size		rb 1
	.reserved	rb 1
	.blocks		rw 1
	.offset		rw 1
	.segment	rw 1
	.lba		rd 2
egos
Member
Member
Posts: 612
Joined: Fri Nov 16, 2007 1:59 pm

Re: BIOS int13h function 42h problem

Post by egos »

FlashBurn wrote:Ok, because of that I´ve written, that my
MBR code is working.
Who did tell about MBR? I meant both kinds of boot loaders (MBR and stage 1). But probably you have problem with FAT16.
If you have seen bad English in my words, tell me what's wrong, please.
FlashBurn
Member
Member
Posts: 313
Joined: Fri Oct 20, 2006 10:14 am

Re: BIOS int13h function 42h problem

Post by FlashBurn »

Who did tell about MBR? I meant both kinds of boot loaders (MBR and stage 1). But probably you have problem with FAT16.
Ok, I´m booting from a CF-Card. So the BIOS first loads my MBR which uses function 42h to load my bootsector and this is working on all PCs! Because of that I can say that my MBR code is working and this also means the PC has function 42h. I also think that my FAT16 code is working, because I have no problem with not finding something, but only with reading sectors from disk.
Maybe I should also say that I use the same CF-Card for all PCs I tested this code on, so because of that I can also say my FAT16 code is working.
gerryg400
Member
Member
Posts: 1801
Joined: Thu Mar 25, 2010 11:26 pm
Location: Melbourne, Australia

Re: BIOS int13h function 42h problem

Post by gerryg400 »

Flashburn, I had a quick look only.

It seems your MBR code checks for the int 13 extension and then uses it if it is present. If it is not present it jmps to .old and uses int 13 func 2. BUT your bootsector code does not check and always uses func 42. Why ?

Maybe this is why MBR works on all machines.
If a trainstation is where trains stop, what is a workstation ?
FlashBurn
Member
Member
Posts: 313
Joined: Fri Oct 20, 2006 10:14 am

Re: BIOS int13h function 42h problem

Post by FlashBurn »

@gerryg400
As I said, I know that the board (we speak of a modern board!) has the function 42h because I know that my MBR does load the bootsector with this function (because I had debug code in my MBR to know which function is used)!

Ok, so now for all, the board supports function 42h and my MBR uses this function to load my bootsector. So the conclusion is that the fault lies in my bootsector, but the point is that this code does work on almost all PCs, but not on a handful (only Server-boards and maybe also only AMIBIOS boards).
I also thought that the problem is that I not zero the DAP memory, but I also did that and it didn´t help.
User avatar
bewing
Member
Member
Posts: 1401
Joined: Wed Feb 07, 2007 1:45 pm
Location: Eugene, OR, US

Re: BIOS int13h function 42h problem

Post by bewing »

You are setting dap.size wrong. You are putting a word of 0x1000 into the size and reserved bytes.
This will put a 0 into the size byte (which is wrong). And a 0x10 into the reserved byte (which is wrong).
FlashBurn
Member
Member
Posts: 313
Joined: Fri Oct 20, 2006 10:14 am

Re: BIOS int13h function 42h problem

Post by FlashBurn »

@bewing

You are my god ;)

This wasn´t the real failure, but it helped me find the real one! The problem was that I not zeroed all the memory of the DAP and this was a problem on some PCs and as I changed my code to zero the memory, I also introduced a bug (the one you just found) :(

So now it is working on this board and I assume that it also works on the other boards were it wasn´t working.

So thanks!
Post Reply