FAT filesystem

This commit is contained in:
SowinskiBraeden committed 2023-06-05 09:20:10 -07:00
1 parent 0fa911690d
commit 21df816061
3 files changed
+211 -79

No files matched your search

Executable
+1
View File
@@ -0,0 +1 @@
qemu-system-i386 -fda build/main_floppy.img
+195 -51
View File
@@ -1,7 +1,7 @@
org 0x7C00 org 0x7C00
bits 16 bits 16
%define ENDL 0x0A %define ENDL 0x0D, 0x0A
; ;
; FAT12 header ; FAT12 header
@@ -36,7 +36,189 @@ ebr_system_id: db 'FAT12 ' ; 8 bytes
; ;
start: start:
jmp main ; setup data segments
mov ax, 0 ; can't write to ds/es directly
mov ds, ax
mov es, ax
; setup stack
mov ss, ax
mov sp, 0x7C00 ; stack grows downwards from where we are loaded in memory
; some BIOSes might start us at 07C0:0000 instead of 0000:7C00, make sure we are in the
; expected location
push es
push word .after
retf
.after:
; read something from floppy disk
; BIOS should set DL to drive number
mov [ebr_drive_number], dl
; show loading message
mov si, msg_loading
call puts
; read drive parametes (sectors per track and head count),
; instead of relying on data on formatted disk
push es
mov ah, 08h
int 13h
jc floppy_error
pop es
and cl, 0x3F ; remove top 2 bits
xor ch, ch
mov [bdb_sectors_per_track], cx ; sector count
inc dh
mov [bdb_heads], dh ; head count
; read FAT root directory
mov ax, [bdb_sectors_per_fat] ; compute LBA of root directory = reserved + fats * sectors_per_fat
mov bl, [bdb_fat_count]
xor bh, bh
mul bx ; ax = (fats * sectors_per_fat)
add ax, [bdb_reserved_sectors] ; ax = LBA of root directory
push ax
; compute size of root directory = (32 * number_of_entries) / bytes_per_sector
mov ax, [bdb_dir_entries_count]
shl ax, 5 ; ax *= 32
xor dx, dx ; dx = 0
div word [bdb_bytes_per_sector] ; number of sectors we need to read
test dx, dx ; if dx != 0, add 1
jz .root_dir_after
inc ax ; division remainder != 0, add 1
; this means we have a sector only partially filled with entries
.root_dir_after:
; read root directory
mov cl, al ; cl = number of sectors to read = size of root directory
pop ax ; ax = LBA of root directory
mov dl, [ebr_drive_number] ; dl = drive number (we saved it previously)
mov bx, buffer ; es:bx = buffer
call disk_read
; search for kernel.bin
xor bx, bx
mov di, buffer
.search_kernel:
mov si, file_kernel_bin
mov cx, 11 ; compare up to 11 characters
push di
repe cmpsb
pop di
je .found_kernel
add di, 32
inc bx
cmp bx, [bdb_dir_entries_count]
jl .search_kernel
; kernel not found
jmp kernel_not_found_error
.found_kernel:
; di should have the address to the entry
mov ax, [di + 26] ; first logical cluster field (offset 26)
mov [kernel_cluster], ax
; load FAT from disk into memory
mov ax, [bdb_reserved_sectors]
mov bx, buffer
mov cl, [bdb_sectors_per_fat]
mov dl, [ebr_drive_number]
call disk_read
; read kernel and process FAT chain
mov bx, KERNEL_LOAD_SEGMENT
mov es, bx
mov bx, KERNEL_LOAD_OFFSET
.load_kernel_loop:
; read next cluster
mov ax, [kernel_cluster]
add ax, 31 ; first cluster = (cluster numer - 2) * sectors_per_cluster + start_sector
; start sector = reserved + fats + root directory size = 1 + 18 + 134 == 33
mov cl, 1
mov dl, [ebr_drive_number]
call disk_read
add bx, [bdb_bytes_per_sector]
; compute location of next cluster
mov ax, [kernel_cluster]
mov cx, 3
mul cx
mov cx, 2
div cx ; ax = index of entry in FAT, dx = cluster mod 2
mov si, buffer
add si, ax
mov ax, [ds:si] ; read entry from FAT table at index ax
or dx, dx
jz .even
.odd:
shr ax, 4
jmp .next_cluster_after
.even:
and ax, 0x0FFF
.next_cluster_after:
cmp ax, 0x0FF8 ; end of chain
jae .read_finish
mov [kernel_cluster], ax
jmp .load_kernel_loop
.read_finish:
; jump to our kernel
mov dl, [ebr_drive_number] ; boot device in dl
mov ax, KERNEL_LOAD_SEGMENT ; set segment registers
mov ds, ax
mov es, ax
jmp KERNEL_LOAD_SEGMENT:KERNEL_LOAD_OFFSET
jmp wait_key_and_reboot ; should never happen
cli ; disable interrupts, this way CPU can't get out of "halt" state
hlt
;
; Error handlers
;
floppy_error:
mov si, msg_read_failed
call puts
jmp wait_key_and_reboot
kernel_not_found_error:
mov si, msg_kernel_not_found
call puts
jmp wait_key_and_reboot
wait_key_and_reboot:
mov ah, 0
int 16h ; wait for keypress
jmp 0FFFFh:0 ; jump to beginning of BIOS, should reboot
.halt:
cli ; disable interrupts, this way CPU can't get out of "halt" state
hlt
; ;
; Prints a string to the screen. ; Prints a string to the screen.
@@ -63,51 +245,6 @@ puts:
pop si pop si
ret ret
main:
; setup data segments
mov ax, 0 ; can't write to ds/es directly
mov ds, ax
mov es, ax
; setup stack
mov ss, ax
mov sp, 0x7C00 ; stack grows downwards from where we are loaded in memory
; read something from floppy disk
; BIOS should set DL to drive number
mov [ebr_drive_number], dl
mov ax, 1 ; LBA=1, second sector from disk
mov cl, 1 ; 1 sector to read
mov bx, 0x7E00 ; data should be after the bootloader
call disk_read
; print hello wrold message
mov si, msg_hello
call puts
cli ; disable interrupts, this way CPU can't get out of "halt" state
hlt
;
; Error handlers
;
floppy_error:
mov si, msg_read_failed
call puts
jmp wait_key_and_reboot
wait_key_and_reboot:
mov ah, 0
int 16h ; wait for keypress
jmp 0FFFFh:0 ; jump to beginning of BIOS, should reboot
.halt:
cli ; disable interrupts, this way CPU can't get out of "halt" state
hlt
; ;
; Disk routines ; Disk routines
; ;
@@ -214,9 +351,16 @@ disk_reset:
popa popa
ret ret
msg_hello: db 'Hello World!', ENDL, 0 msg_loading: db 'Loading...', ENDL, 0
msg_read_failed: db 'Read from disk failed!', ENDL, 0 msg_read_failed: db 'Read from disk failed!', ENDL, 0
msg_kernel_not_found: db 'KERNEL.BIN file not found!', ENDL, 0
file_kernel_bin: db 'KERNEL BIN'
kernel_cluster: dw 0
KERNEL_LOAD_SEGMENT equ 0x2000
KERNEL_LOAD_OFFSET equ 0
times 510-($-$$) db 0 times 510-($-$$) db 0
dw 0AA55h dw 0AA55h
buffer:
+15 -28
View File
@@ -1,10 +1,17 @@
org 0x7C00 org 0x0
bits 16 bits 16
%define ENDL 0x0A %define ENDL 0x0D, 0x0A
start: start:
jmp main
; print message
mov si, msg_hello
call puts
.halt:
cli
hlt
; ;
; Prints a string to the screen. ; Prints a string to the screen.
@@ -15,43 +22,23 @@ puts:
; save registers we will modify ; save registers we will modify
push si push si
push ax push ax
push bx
.loop: .loop:
lodsb ; loads next character in al lodsb ; loads next character in al
or al, al ; verify if next character is null? or al, al ; verify if next character is null?
jz .done jz .done
mov ah, 0x0e ; call bios interrupt mov ah, 0x0E ; call bios interrupt
mov bh, 0x10 ; set page number to 0
int 0x10 int 0x10
jmp .loop jmp .loop
.done: .done:
pop bx
pop ax pop ax
pop si pop si
ret ret
main: msg_hello: db 'Hello World!', ENDL, 0
; setup data segments
mov ax, 0 ; can't write to ds/es directly
mov ds, ax
mov es, ax
; setup stack
mov ss, ax
mov sp, 0x7C00 ; stack grows downwards from where we are loaded in memory
; print message
mov si, ms_hello
call puts
hlt
.halt:
jmp .halt
ms_hello: db 'Hello World!', ENDL, 0
times 510-($-$$) db 0
dw 0AA55h