Unknown problem reading kernel from second stage bootloader
Posted: Wed Dec 16, 2020 5:18 pm
I'm not sure what the problem is, I use this function to read sectors from disk:
I use it load the VBR from the MBR and the second stage bootloader from the first stage so it should work perfectly.
I wrote some function to interact with the FAT16 and I use them in the first stage bootloader, so they should be fine. The only one that I doubt is the one that actually loads the file, since the second stage is not larger than a cluster I haven't tested it for multuple clusters. Anyway at least one cluster should be loaded, this is not the important part.
In the LoadFile function after checking if the file exists I load it into memory 1 cluster at a time. I read a cluster by reading a bunch of sectors using the function above.
This exact function works to load the second stage from the first stage but doesn't even load a sector when I try to load the kernel.
I checked all the register to be sure that the values were correct before calling ReadSectorsLBA and they are. I don't know what to do. I'm posting the important bits here but I'll also link the github repository, the code is in the boot folder: https://github.com/DefEnge/test-kernel.
Here is the LoadFile function:
It relies on some functions, theese are the info about them (I'm 99.9% sure they work so I'll not post them here. If you want to check or if you obviusly need a minimail example to replicate they are in the repo linked above in boot/include/fat16.inc):
Code: Select all
;***********************************;
; Reads a series of sectors ;
; Parameters: ;
; dl => bootdrive ;
; ax => sectors count ;
; ebx => address to load to ;
; ecx => LBA address ;
; Returns: ;
; cf => set if error ;
;***********************************;
ReadSectorsLBA:
.init:
pusha
mov ah, 0x00 ; Reset disk function
int 0x13
jc .done
popa
.readSec:
mov [LBA_Packet.block_cout], ax
mov [LBA_Packet.transfer_buffer], ebx
mov [LBA_Packet.lba_value], ecx
mov si, LBA_Packet
mov ah, 0x42 ; Read sectors function
int 0x13
.done
ret
align 4
LBA_Packet:
.packet_size db 0x10 ; use_transfer_64 ? 10h : 18h
.reserved db 0x00 ; always zero
.block_cout dw 0x00 ; number of sectors to read
.transfer_buffer dd 0x00 ; address to load in ram
.lba_value dq 0x00 ; LBA addres value
I wrote some function to interact with the FAT16 and I use them in the first stage bootloader, so they should be fine. The only one that I doubt is the one that actually loads the file, since the second stage is not larger than a cluster I haven't tested it for multuple clusters. Anyway at least one cluster should be loaded, this is not the important part.
In the LoadFile function after checking if the file exists I load it into memory 1 cluster at a time. I read a cluster by reading a bunch of sectors using the function above.
This exact function works to load the second stage from the first stage but doesn't even load a sector when I try to load the kernel.
I checked all the register to be sure that the values were correct before calling ReadSectorsLBA and they are. I don't know what to do. I'm posting the important bits here but I'll also link the github repository, the code is in the boot folder: https://github.com/DefEnge/test-kernel.
Here is the LoadFile function:
Code: Select all
;************************************;
; Load file ;
; Parameters: ;
; es:si => File name ;
; ebx => Buffer to load file to ;
; Returns: ;
; ax => -1 on error, 0 on success ;
;************************************;
LoadFile:
.findFile:
call FindFile ; find file using name in es:si
cmp ax, -1
jne .loadFilePre
; file not found
mov ax, -1 ; error code
ret
.loadFilePre:
; get starting cluster
mov edx, dword ROOT_OFFSET ; edx points to the rood dir
add edx, edi ; edx + edi is the index of the file retrived with findFile
mov ax, word [dword edx + 0x001A] ; retrive cluster from root entry
mov word [cluster], ax
; get 0th cluster address
call GetRootInfo
add eax, ecx
mov dword [first_cluster_sector], eax
call LoadFAT
.nextCluster:
xor ecx, ecx
xor ax, ax
mov cx, word [cluster]
sub cx, 2
add ecx, dword [first_cluster_sector]
mov dl, byte [bpb_DriveNumber]
mov al, byte [bpb_SectorsPerCluster]
call ReadSectorsLBA
; "breakpoint" that activates only in second stage
%ifdef SECOND_STAGE
jmp $
%endif
; get next cluster from fat table
xor eax, eax
mov ax, word [cluster]
add eax, FAT_OFFSET
mov bx, word [dword eax]
mov word [cluster], bx
; test if it was the last cluster
cmp word [cluster], 0xFFFF
je .done
cmp word [cluster], 0xF8FF
je .done
; increase address
xor eax, eax
mov ax, word [bpb_SectorsPerCluster]
mul word [bpb_BytesPerSector]
add ebx, eax
jmp .nextCluster
.done:
mov ax, 0
ret
cluster dw 0x0000
first_cluster_sector dd 0x00000000
Code: Select all
;***********************************************;
; Search for filename in root table ;
; Parameters: ;
; es:si => File name ;
; Returns: ;
; ax => File index number in directory table. ;
; es:di => Location of the file root entry ;
;***********************************************;
FindFile
;****************************;
; Loads FAT table to FAT_SEG ;
;****************************;
LoadFAT
;*********************************;
; Sets Rot Directory informations ;
; Returns: ;
; edx => location in sectors. ;
; ax => size in sectors ;
;*********************************;
GetRootInfo