can't get my fat12 bootloader to work
Posted: Sun Mar 06, 2016 7:40 pm
I'm trying to get my bootloader to load my kernel from a file on a fat12 floppy but its not exactly working. My code for the fat12 loading is based on this tutorial http://www.brokenthorn.com/Resources/OSDev6.html, but my boot loader does some other stuff outside the scope of my problems. The bootlader will find the file while looking through the directory but it crashes when it actually tries to load the file. Bochs will give me this error and then it will get stuck
anyway here is my code, maybe someone can help me figure out why this isn't working.
boot_sect.asm:
fatload.asm:
disk.asm:
, when it tries to load the clusters where the file is.int13_cdrom: function 02, ELDL out of range ff
anyway here is my code, maybe someone can help me figure out why this isn't working.
boot_sect.asm:
Code: Select all
[org 0x7c00]
start: jmp begin
nop
%assign _bytes_per_sector 512
%assign _sectors_per_cluster 1
%assign _reserved_sectors 1
%assign _number_of_FATs 2
%assign _root_entries 224
%assign _total_sectors 2880
%assign _media 0xf8
%assign _sectors_per_FAT 9
%assign _sectors_per_track 18
%assign _heads_per_cylinder 2
%assign _hidden_sectors 0
%assign _total_sectors_big 0
%assign _drive_number 0
%assign _unused 0
%assign _ext_boot_signature 0x29
%assign _serial_number 0xa0a1a2a3
; BIOS Parameter Block
bp_OEM db "EMS OS "
bp_bytes_per_sector: dw _bytes_per_sector
bp_sectors_per_cluster: db _sectors_per_cluster
bp_reserved_sectors: dw _reserved_sectors
bp_number_of_FATs: db _number_of_FATs
bp_root_entries: dw _root_entries
bp_total_sectors: dw _total_sectors
bp_media: db _media
bp_sectors_per_FAT: dw _sectors_per_FAT
bp_sectors_per_track: dw _sectors_per_track
bp_heads_per_cylinder: dw _heads_per_cylinder
bp_hidden_sectors: dd _hidden_sectors
bp_total_sectors_big: dd _total_sectors_big
bs_drive_number: db _drive_number
bs_unused: db _unused
bs_ext_boot_signature: db _ext_boot_signature
bs_serial_number: dd _serial_number
bs_volume_label: db "EMS FLOPPY "
bs_file_system: db "FAT12 "
KERNEL_OFFSET equ 0x1000 ; This is the memory address where our kernel goes
begin:
mov [boot_info + multiboot_info.bootDevice], dl ; Save the index of the boot drive
mov bp, 0x9000 ; Set up the stack.
mov sp, bp
call getmem
call fat_load
mov ax, 0x01
int 0x10
jmp switch_to_pm ; Switch to protected mode
%include "disk.asm"
%include "gdt.asm"
%include "switchtopm.asm"
%include "memmap.asm"
%include "multiboot.asm"
%include "fatload.asm"
[bits 32]
; In protected mode now
BEGIN_PM :
mov eax, 0x2badb002 ;multiboot magic
push dword boot_info
call KERNEL_OFFSET ; Jumping into C and Kernel land
; Multiboot header
boot_info:
istruc multiboot_info
at multiboot_info.flags, dd 0
at multiboot_info.memoryLo, dd 0
at multiboot_info.memoryHi, dd 0
at multiboot_info.bootDevice, dd 0
at multiboot_info.cmdLine, dd 0
at multiboot_info.mods_count, dd 0
at multiboot_info.mods_addr, dd 0
at multiboot_info.syms0, dd 0
at multiboot_info.syms1, dd 0
at multiboot_info.syms2, dd 0
at multiboot_info.mmap_length, dd 0
at multiboot_info.mmap_addr, dd 0
at multiboot_info.drives_length, dd 0
at multiboot_info.drives_addr, dd 0
at multiboot_info.config_table, dd 0
at multiboot_info.bootloader_name, dd 0
at multiboot_info.apm_table, dd 0
at multiboot_info.vbe_control_info, dd 0
at multiboot_info.vbe_mode_info, dw 0
at multiboot_info.vbe_interface_seg, dw 0
at multiboot_info.vbe_interface_off, dw 0
at multiboot_info.vbe_interface_len, dw 0
iend
; Bootsector padding
times 510 -( $ - $$ ) db 0
; magic number
dw 0xaa55
Code: Select all
%assign root_size (32 * _root_entries) / _bytes_per_sector
%assign fats_size (_number_of_FATs * _sectors_per_FAT)
%assign root_location fats_size + _reserved_sectors
%assign datasector root_location + root_size
%assign cluster_size _sectors_per_cluster * _bytes_per_sector
fat_load :
; read root directory into memory (0x200)
mov cx, root_size
mov ax, root_location
mov bx, 0x0200
call disk_load
; browse root directory for binary image
mov cx, _root_entries ; load loop counter
mov di, 0x0200 ; locate first root entry
.LOOP:
push cx
mov cx, 0x000B ; eleven character name
mov si, file_name ; image name to find
push di
rep cmpsb ; test for entry match
pop di
je LOAD_FAT
pop cx
add di, 0x0020 ; queue next directory entry
loop .LOOP
FAILURE:
jmp $ ; did not find kernel image
LOAD_FAT:
; save starting cluster of boot image
mov dx, WORD [di + 0x001A]
mov WORD [cluster], dx ; file's first cluster
; read FAT into memory (0x0200)
mov cx, fats_size ; sectors used by FATs
mov ax, _reserved_sectors ; adjust for bootsector
mov bx, 0x0200
call disk_load
push KERNEL_OFFSET ; push kernel destination address onto the stack
LOAD_IMAGE:
pop bx
mov ax, WORD [cluster] ; cluster to read
; convert cluster to LBA
sub ax, 0x0002 ; zero base cluster number
mov cx, _sectors_per_cluster ; convert byte to word
mul cx
add ax, datasector ; base data sector
call disk_load
push bx
; compute next cluster
mov ax, WORD [cluster] ; cluster + cluster / 2
mov bx, ax
shr bx, 0x0001 ; divide by two
add bx, ax
mov dx, WORD [bx + 0x0200] ; read two bytes from FAT (0x0200)
test ax, 0x0001
jnz .ODD_CLUSTER
.EVEN_CLUSTER:
and dx, 0000111111111111b ; take low twelve bits
jmp .DONE
.ODD_CLUSTER:
shr dx, 0x0004 ; take high twelve bits
.DONE:
mov WORD [cluster], dx ; store new cluster
cmp dx, 0x0FF0 ; test for end of file
jb LOAD_IMAGE
DONE:
ret ; kernel image is loaded at KERNEL_OFFSET
cluster dw 0x0000
file_name db "KERNAL SYS"
Code: Select all
; load cx sectors to ES:BX from boot drive at sector ax
disk_load:
.MAIN:
push ax
push cx
.LBACHS:
xor dx, dx ; prepare dx:ax for operation
div word [bp_sectors_per_track] ; calculate
inc dl ; adjust for sector 0
mov cl, dl
xor dx, dx ; prepare dx:ax for operation
div word [bp_heads_per_cylinder] ; calculate
mov dh, dl
mov ch, al
mov ah, 0x02 ; BIOS read sector
mov al, 0x01 ; read one sector
mov dl, BYTE [boot_info + multiboot_info.bootDevice] ; drive
int 0x13 ; invoke BIOS
.SUCCESS:
pop cx
pop ax
add bx, _bytes_per_sector ; queue next buffer
inc ax ; queue next sector
loop .MAIN ; read next sector
ret