triple fault on file load

If you are new to OS Development, plan on spending some time here first before going into the other forums.

Moderator:Moderators

Post Reply
xixpsychoxix
Posts:59
Joined:Tue Oct 13, 2009 8:49 pm
triple fault on file load

Post by xixpsychoxix » Mon Dec 02, 2013 12:51 pm

Hello all! It feels like forever since I've been here! Anyways, I started writing a second stage loader and I am having an issue. I am trying to write the code for myself so I can better learn how to do so, and here is the issue I am having. In my FAT12 minidriver for stage 2, I have the following routine to load a file:

Code: Select all

;**********************************************************************
;	_fat12_LoadFile: load a specified file from the current disk
;	Parameters: DS:SI - filename, ES:BX - buffer to file
;	Returns: On error, CF set, AX = error code
;**********************************************************************

_fat12_LoadFile:
	
	push es		; save es
	push bx		; and bx
	
	; first, try to load the root directory
	call _LoadRootDir
	jc .LoadRootError
	
	; now, try to load the FAT tables
	call _LoadFileTable
	jc .LoadFATError
	
	; try to locate the file
	call _LocateFile
	jc .LocateError
	
.LoadFileImage:

	pop bx		; here's where we are
	pop es		; storing our file
	
	push ax				; save the current cluster number
	call _clusterLBA			; translate to LBA
	xor cx,cx				; zero out cx
	mov cl,byte [bpbSectorsPerCluster]		; and store the number of sectors to read in cl
	call _readSectors			; read the sectors
	jc .ClusterReadError			; if the carry flag is set, we have a cluster read error
	pop ax				; restore the cluster number
	
	; save es and bx again
	push es
	push bx
	
	; compute the next cluster
	mov cx,ax				; store a copy of the cluster
	mov dx,ax				; in cx and dx
	shr dx,0x0001			; divide dx by two
	add cx,dx				; adjust for 3/2
	
	push word FAT_SEGMENT
	pop es
	xor bx,bx			; the offset of the FAT
	
	add bx,cx			; add the offset of the cluster
	mov dx,word [es:bx]		; read the next cluster from the FAT
	test ax,0x0001		; see if the cluster is even or odd
	jnz .OddCluster		; and handle if odd
	
.EvenCluster:

	and dx,0000111111111111b	; get low twelve bits
	jmp .ClusterDone		; and finish this cluster
	
.OddCluster:

	shr dx,0x04			; get high twelve bits
	
.ClusterDone:

	mov ax,dx			; put the cluster into ax
	cmp dx,0x0ff0		; check for end-of-file cluster
	jb .LoadFileImage		; and if it isn't EOF, keep reading
	
.Success:

	pop bx
	pop es
	xor ax,ax
	
	ret
	
.LoadRootError:

	stc
	mov ax,1
	jmp .ErrorReturn
	
.LoadFATError:

	stc
	mov ax,2
	jmp .ErrorReturn
	
.LocateError:

	stc
	mov ax,3
	jmp .ErrorReturn
	
.ClusterReadError:

	stc
	mov ax,4
	jmp .ErrorReturn

.ErrorReturn:

	pop bx
	pop es
	
	ret
The routines that are called by this function are all tested working (as far as I can tell). I am calling the above routine as such:

Code: Select all

; the minidriver started. Load the kernel image
	xor ax,ax
	mov es,ax
	mov bx,IMAGE_RMODE_BASE
	
	mov si,str_imgName
	call _fat12_LoadFile
	jc KERNEL_LOAD_EXCEPTION
Can anyone see any obvious reasons why the CPU would triple-fault from this code? The addresses are defined as:

Code: Select all

%define IMAGE_RMODE_BASE 0x3000
%define ROOT_SEGMENT 0x2e0
%define FAT_SEGMENT 0x2c0
%define ROOT_OFFSET 0x2e00
I traced the stack by looking at the stack operations, and I cannot seem to figure out what the error is. As far as I know, there is no stack error causing the triple fault, so I am unsure of what is going on here. Any ideas?

xixpsychoxix
Posts:59
Joined:Tue Oct 13, 2009 8:49 pm

Re: triple fault on file load

Post by xixpsychoxix » Mon Dec 02, 2013 3:46 pm

Ok, so I think (untested!) I found the problem. My _LoadRootDir function loads the root directory at (02e0:0000). My _LoadFileTable function is loading the file table to (02c0:0000). I am not sure if the FAT is overwriting my root directory, but if I return without trying to load the file (right after _LocateFile) I am not getting the triple fault. As soon as I try to load the file's sectors, however, I am triple faulting. I edited the code so that my _LoadRootDir loads the root directory to (02c0:0000) and the _LoadFileTable does the same. I then made the following change:

Code: Select all

_fat12_LoadFile:
   
   push es      ; save es
   push bx      ; and bx
   
   ; first, try to load the root directory
   call _LoadRootDir
   jc .LoadRootError
      
   ; try to locate the file
   call _LocateFile
   jc .LocateError
   
   ; the file was found - load the FAT table
   call _LoadFileTable
   jc .LoadFATError

.LoadFileImage:

   pop bx      ; here's where we are
   pop es      ; storing our file
   
   push ax            ; save the current cluster number
   call _clusterLBA         ; translate to LBA
   xor cx,cx            ; zero out cx
   mov cl,byte [bpbSectorsPerCluster]      ; and store the number of sectors to read in cl
   call _readSectors         ; read the sectors
   jc .ClusterReadError         ; if the carry flag is set, we have a cluster read error
   pop ax            ; restore the cluster number
   
   ; save es and bx again
   push es
   push bx
   
   ; compute the next cluster
   mov cx,ax            ; store a copy of the cluster
   mov dx,ax            ; in cx and dx
   shr dx,0x0001         ; divide dx by two
   add cx,dx            ; adjust for 3/2
   
   push word FAT_SEGMENT
   pop es
   xor bx,bx         ; the offset of the FAT
   
   add bx,cx         ; add the offset of the cluster
   mov dx,word [es:bx]      ; read the next cluster from the FAT
   test ax,0x0001      ; see if the cluster is even or odd
   jnz .OddCluster      ; and handle if odd
   
.EvenCluster:

   and dx,0000111111111111b   ; get low twelve bits
   jmp .ClusterDone      ; and finish this cluster
   
.OddCluster:

   shr dx,0x04         ; get high twelve bits
   
.ClusterDone:

   mov ax,dx         ; put the cluster into ax
   cmp dx,0x0ff0      ; check for end-of-file cluster
   jb .LoadFileImage      ; and if it isn't EOF, keep reading
   
.Success:

   pop bx
   pop es
   xor ax,ax
   
   ret
   
.LoadRootError:

   stc
   mov ax,1
   jmp .ErrorReturn
   
.LoadFATError:

   stc
   mov ax,2
   jmp .ErrorReturn
   
.LocateError:

   stc
   mov ax,3
   jmp .ErrorReturn
   
.ClusterReadError:

   stc
   mov ax,4
   jmp .ErrorReturn

.ErrorReturn:

   pop bx
   pop es
   
   ret
If that was in fact the issue, I should now have overwritten my root directory with my FAT table (since I no longer need it) and should be able to load as normal. I cannot test this right now, but as I type this it becomes apparent to me that the issue is not in initially finding the file (the file is found when present, and not found when absent), but in loading the sectors for the file, so even if my root directory was being overwritten this is most likely NOT the issue.

xixpsychoxix
Posts:59
Joined:Tue Oct 13, 2009 8:49 pm

Re: triple fault on file load

Post by xixpsychoxix » Tue Dec 03, 2013 2:09 am

Problem solved... long story short, extensively taught myself how to use the bochs debugger today. That section rewrite, along with changing my kernel stub (16-bit load routine test version) to assemble as 16-bit, solved the problem Bochs debugger is officially an AMAZING OS programming tool!

pathos
Moderator
Posts:97
Joined:Thu Jan 10, 2008 6:43 pm
Location:USA

Re: triple fault on file load

Post by pathos » Tue Dec 03, 2013 2:28 pm

xixpsychoxix wrote:Bochs debugger is officially an AMAZING OS programming tool!
Yes... yes it is.

Post Reply