FAT16 Example
Posted: Fri Jun 28, 2013 12:57 pm
Hi I have finally read a file with FAT16 in my OS here is the code just in case its useful for anybody
Its not yet complete the code above will only load one sector from the selected file. I'm planning to implement FAT16 more soon.
Hope it helps some one who is trying to load a file with FAT16.
Code: Select all
%define ROOT_DIRECTORY_POS 0x7e00
org 0 ; we start everything at zero
jmp short start
nop
MANU_DESC db 'mkdosfs '
BLOCK_SIZE dw 512
BLOCKS_PER_ALLOCATION_UNIT db 128
RESERVED_BLOCKS dw 1
TOTAL_FATS db 1
TOTAL_ROOT_ENTRIES dw 512
TOTAL_BLOCKS dw 0xffff
MEDIA_DESCRIPTOR db 0xf8
BLOCKS_PER_FAT dw 0x01
BLOCKS_PER_TRACK dw 18
TOTAL_HEADS dw 0x02
HIDDEN_BLOCKS dd 0x00
TOTAL_BLOCKS_2 dd 0x00
DRIVE_NUMBER dw 0x00
EXTENDED_BOOT_SIGNATURE db 0x29
VOLUME_SERIAL_NUMBER dd 0x9d86f18c
VOLUME_LABEL db 'SEAGULL '
FILE_SYSTEM_IDENTIFIER db 'FAT16 '
; Calculated in memory
ROOT_DIRECTORY dw 0x00
DAPACK:
db 0x10
db 0
.len: dw 1
.loc: dd ROOT_DIRECTORY_POS
.sec: dd 0
dd 0
start:
cli
mov ax, 0x7c0
mov ds, ax
mov es, ax
mov sp, 0x1000
mov bp, 0
mov ss, bp
sti
mov byte [DRIVE], dl
; Root Directory Logical Sector = (TOTAL_FATS * BLOCKS_PER_FAT) + (RESERVED_BLOCKS)
mov ax, [TOTAL_FATS]
mul word [BLOCKS_PER_FAT]
add ax, [RESERVED_BLOCKS]
mov word [ROOT_DIRECTORY], ax
; Load root directory
mov word [DAPACK.sec], ax
mov si, DAPACK ; address of "disk address packet"
mov ah, 0x42 ; AL is unused
mov dl, [DRIVE] ; drive number 0 (OR the drive # with 0x80)
int 0x13
jc err
FIND_KERNEL:
cli ; Turn interrupts off when editing segment registers
mov ax, 0x7e0
mov es, ax
sti
mov bx, 0
; Calculate root directory data start - (ROOT_DIRECTORY + (TOTAL_ROOT_ENTRIES/16))
mov ax, [ROOT_DIRECTORY]
mov dx, 16
div dl ; (TOTAL_ROOT_ENTRIES/16), AL = AX / DL
add bx, ax
mov ax, 1
.find:
mov cx, 0
mov si, KERNEL
.repeat:
cmp cx, 11
je .load_clusters
lodsb
cmp al, [es:bx]
jne .next
inc cx
inc bx
jmp .repeat
.next:
mov ax, 32
sub ax, cx
add bx, ax
jmp .find
.load_clusters:
mov ax, 15 ; 15 bytes away from start of cluster number
add bx, ax ; Seek to cluster number
mov ax, [es:bx] ; Grab cluster number
; Time to calculate the LBA of the kernel
; LBA = (cluster-2)*BLOCKS_PER_ALLOCATION_UNIT+(TOTAL_ROOT_ENTRIES/16)+(HIDDEN_BLOCKS+RESERVED_BLOCKS+TOTAL_FATS*BLOCKS_PER_FAT)
mov bx, 2
sub ax, bx ; Subtract 2 from cluster number
mov dl, [BLOCKS_PER_ALLOCATION_UNIT]
mul dl ; AX = AL * BLOCKS_PER_ALLOCATION_UNIT
push ax ; Push AX on to the stack
mov dx, 0
mov ax, [TOTAL_ROOT_ENTRIES]
mov bx, 16
div bx ; DX:AX = TOTAL_ROOT_ENTRIES / 16
mov bx, ax
pop ax ; Pop AX off the stack
add ax, bx ; Add the result on to AX
mov bx, [HIDDEN_BLOCKS] ; NOTE: Hidden blocks is 32 bit. 16 bit will be fine.
mov dx, [RESERVED_BLOCKS]
add bx, dx ; BX = HIDDEN_BLOCKS + RESERVED_BLOCKS
xor dx, dx
mov dl, [TOTAL_FATS]
add bx, dx ; BX += TOTAL_FATS
push ax ; Push AX on to the stack
mov ax, bx
mov dx, [BLOCKS_PER_FAT]
mul dx ; DX:AX = AX * BLOCKS_PER_FAT
mov bx, ax
pop ax ; Pop AX off the stack
add ax, bx ; AX += BX
LOAD_KERNEL:
; Time to load the kernel!
mov word [DAPACK.sec], ax
mov si, DAPACK ; address of "disk address packet"
mov ah, 0x42 ; AL is unused
mov dl, [DRIVE] ; drive number 0 (OR the drive # with 0x80)
int 0x13
jc err
jmp 0x000:0x7e00
err:
mov si, ERROR
call print
print:
pusha
mov ah, 0eh
.repeat:
lodsb
cmp al, 0
je .done
int 10h
jmp .repeat
.done:
popa
ret
KERNEL db "KERNEL BIN", 0
ERROR db "Failed to load sector", 10, 13, 0
DRIVE db 0
times 510-($-$$) db 0 ; fill in the remaining space with zero
dw 0xaa55 ; legacy boot signature
Hope it helps some one who is trying to load a file with FAT16.