FAT filesystem
This commit is contained in:
3 files changed
+209
-77
No files matched your search
+193
-49
@@ -1,7 +1,7 @@
|
||||
org 0x7C00
|
||||
bits 16
|
||||
|
||||
%define ENDL 0x0A
|
||||
%define ENDL 0x0D, 0x0A
|
||||
|
||||
;
|
||||
; FAT12 header
|
||||
@@ -36,7 +36,189 @@ ebr_system_id: db 'FAT12 ' ; 8 bytes
|
||||
;
|
||||
|
||||
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.
|
||||
@@ -63,51 +245,6 @@ puts:
|
||||
pop si
|
||||
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
|
||||
;
|
||||
@@ -214,9 +351,16 @@ disk_reset:
|
||||
popa
|
||||
ret
|
||||
|
||||
msg_hello: db 'Hello World!', ENDL, 0
|
||||
msg_read_failed: db 'Read from disk failed!', ENDL, 0
|
||||
msg_loading: db 'Loading...', 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
|
||||
dw 0AA55h
|
||||
|
||||
buffer:
|
||||
+15
-28
@@ -1,10 +1,17 @@
|
||||
org 0x7C00
|
||||
org 0x0
|
||||
bits 16
|
||||
|
||||
%define ENDL 0x0A
|
||||
%define ENDL 0x0D, 0x0A
|
||||
|
||||
start:
|
||||
jmp main
|
||||
|
||||
; print message
|
||||
mov si, msg_hello
|
||||
call puts
|
||||
|
||||
.halt:
|
||||
cli
|
||||
hlt
|
||||
|
||||
;
|
||||
; Prints a string to the screen.
|
||||
@@ -15,43 +22,23 @@ puts:
|
||||
; save registers we will modify
|
||||
push si
|
||||
push ax
|
||||
push bx
|
||||
|
||||
.loop:
|
||||
lodsb ; loads next character in al
|
||||
or al, al ; verify if next character is null?
|
||||
jz .done
|
||||
|
||||
mov ah, 0x0e ; call bios interrupt
|
||||
mov ah, 0x0E ; call bios interrupt
|
||||
mov bh, 0x10 ; set page number to 0
|
||||
int 0x10
|
||||
|
||||
jmp .loop
|
||||
|
||||
.done:
|
||||
pop bx
|
||||
pop ax
|
||||
pop si
|
||||
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
|
||||
|
||||
; 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
|
||||
msg_hello: db 'Hello World!', ENDL, 0
|
||||
Reference in new issue
Block a user