FAT filesystem
This commit is contained in:
3 files changed
+208
-76
No files matched your search
+192
-48
@@ -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
@@ -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
|
|
||||||
Reference in new issue
Block a user