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