243 lines
4 KiB
NASM
243 lines
4 KiB
NASM
[BITS 16]
|
|
[ORG 0x7c00]
|
|
|
|
; check reading reading media with lba
|
|
; read 2 first block (superblock & inode)
|
|
; validate that it's a StupidFS by checking magic
|
|
; check if inode 2 is present (loader reside in inode 2)
|
|
; get loader size
|
|
; iterate direct zone and load data to LOADER_BASE
|
|
; iterate double indirect and load data (in order to keep things simple we won't support loader > 69632 bytes)
|
|
|
|
LOADER_BASE equ 0x1000
|
|
DISK_BUFFER equ 0x8000
|
|
STPDFS_MAGIC equ 0x44505453
|
|
BLOCK_SIZE equ 512
|
|
INODE_SIZE equ 0x46
|
|
INODE_ALLOCATED equ (1<<15)
|
|
CR equ 0xD
|
|
LF equ 0xA
|
|
|
|
struc inode
|
|
.mode: resw 1
|
|
.nlink: resw 1
|
|
.uid: resw 1
|
|
.gid: resw 1
|
|
.flags: resw 1
|
|
.size: resd 1
|
|
.zones: resd 10
|
|
.actime: resq 1
|
|
.modtime: resq 1
|
|
endstruc
|
|
|
|
jmp start
|
|
nop
|
|
|
|
bpb:
|
|
db 0, 0, 0
|
|
.oem_id: db "STUPIDFS"
|
|
.sector_size: dw 512
|
|
.sects_per_cluster: db 0
|
|
.reserved_sects: dw 0
|
|
.fat_count: db 0
|
|
.root_dir_entries: dw 0
|
|
.sector_count: dw 0
|
|
.media_type: db 0
|
|
.sects_per_fat: dw 0
|
|
.sects_per_track: dw 18
|
|
.head_count: dw 2
|
|
.hidden_sects: dd 0
|
|
.sector_count_big: dd 0
|
|
.drive_num: db 0
|
|
.reserved: db 0
|
|
.signature: db 0
|
|
.volume_id: dd 0
|
|
.volume_label: db "STPD.MKFS "
|
|
.filesystem_type: times 8 db 0
|
|
|
|
start:
|
|
cli
|
|
cld
|
|
jmp 0x0:.canonicalize_cs
|
|
|
|
.canonicalize_cs:
|
|
xor ax, ax
|
|
mov ds, ax
|
|
mov ss, ax
|
|
mov es, ax
|
|
mov sp, 0x7c00
|
|
|
|
mov [bpb.drive_num], dl
|
|
|
|
; ensure lba mode is supported
|
|
mov ah, 0x41
|
|
mov bx, 0x55AA
|
|
int 0x13
|
|
jc .err_lba
|
|
|
|
; reset disk
|
|
.reset_disk:
|
|
mov dl, [bpb.drive_num]
|
|
xor ah, ah
|
|
int 0x13
|
|
jc .reset_disk
|
|
|
|
; read superblock
|
|
mov ax, DISK_BUFFER/0x10
|
|
mov es, ax
|
|
|
|
; load two sector in memory
|
|
; superblock and first inodes
|
|
mov eax, 1
|
|
mov cx, 2
|
|
xor bx, bx
|
|
call disk_read_sectors
|
|
|
|
mov dword eax, [DISK_BUFFER]
|
|
cmp eax, STPDFS_MAGIC
|
|
jne .err_magic
|
|
|
|
; inode 0 bad inode
|
|
; inode 1 root dir
|
|
; inode 2 is loader, let's keep things easy
|
|
mov ax, word [DISK_BUFFER + 512 + INODE_SIZE * 2 + inode.flags]
|
|
and ax, INODE_ALLOCATED
|
|
jz .err_no_loader
|
|
|
|
mov dword eax, [DISK_BUFFER + 512 + INODE_SIZE * 2 + inode.size] ; size
|
|
mov dword [uFsize], eax
|
|
|
|
; copy data to LOADER_BASE
|
|
mov ax, LOADER_BASE/0x10
|
|
mov es, ax
|
|
|
|
; direct read
|
|
xor edx, edx
|
|
xor ebx, ebx
|
|
.direct_loop:
|
|
cmp ebx, [uFsize]
|
|
jg .all_read
|
|
|
|
mov eax, edx
|
|
shl eax, 2
|
|
add eax, DISK_BUFFER + 512 + INODE_SIZE * 2 + inode.zones
|
|
|
|
push edx
|
|
|
|
; copy block
|
|
mov eax, [eax]
|
|
mov cx, 1
|
|
call disk_read_sectors
|
|
|
|
pop edx
|
|
|
|
add ebx, BLOCK_SIZE
|
|
inc edx
|
|
cmp edx, 7
|
|
jb .direct_loop
|
|
|
|
xchg bx, bx
|
|
|
|
.indirect_read:
|
|
push ebx
|
|
|
|
mov ax, DISK_BUFFER/0x10
|
|
mov es, ax
|
|
|
|
mov eax, [DISK_BUFFER + 512 + INODE_SIZE * 2 + inode.zones + 28] ;zones[7] == indirect
|
|
mov cx, 1
|
|
xor bx, bx
|
|
call disk_read_sectors
|
|
|
|
xchg bx, bx
|
|
|
|
mov ax, LOADER_BASE/0x10
|
|
mov es, ax
|
|
pop ebx
|
|
|
|
xor edx, edx
|
|
.indirect_loop:
|
|
cmp ebx, [uFsize]
|
|
jg .all_read
|
|
mov eax, edx
|
|
shl eax, 2
|
|
add eax, DISK_BUFFER
|
|
|
|
mov eax, [eax]
|
|
mov cx, 1
|
|
call disk_read_sectors
|
|
|
|
add ebx, BLOCK_SIZE
|
|
inc edx
|
|
cmp edx, 128
|
|
jbe .indirect_loop
|
|
|
|
.all_read:
|
|
|
|
; jump to loader
|
|
mov dl, [bpb.drive_num]
|
|
jmp 0x0:LOADER_BASE
|
|
|
|
|
|
.err_no_loader:
|
|
mov si, szErrorNoLoader
|
|
call bios_print
|
|
jmp .end
|
|
.err_magic:
|
|
mov si, szErrorNoLoader
|
|
call bios_print
|
|
jmp .end
|
|
.err_read:
|
|
mov si, szErrorRead
|
|
call bios_print
|
|
jmp .end
|
|
.err_lba:
|
|
mov si, szErrorLBA
|
|
call bios_print
|
|
.end:
|
|
hlt
|
|
jmp $
|
|
|
|
bios_print:
|
|
lodsb
|
|
or al, al
|
|
jz .end
|
|
mov ah, 0x0E
|
|
int 0x10
|
|
jmp bios_print
|
|
.end:
|
|
ret
|
|
|
|
szErrorNoLoader: db "Loader not found", CR, LF, 0
|
|
szErrorBadMagic: db "Err: magic", CR, LF, 0
|
|
szErrorLBA: db "Err: LBA", CR, LF, 0
|
|
szErrorRead: db "Err: read", CR, LF, 0
|
|
uFsize: dd 0
|
|
|
|
disk_read_sectors:
|
|
mov word [disk_packet.sectors], cx
|
|
mov word [disk_packet.segment], es
|
|
mov word [disk_packet.offset], bx
|
|
mov dword [disk_packet.lba], eax
|
|
mov si, disk_packet
|
|
mov dl, [bpb.drive_num]
|
|
mov ah, 0x42
|
|
int 0x13
|
|
jc start.err_read
|
|
ret
|
|
|
|
disk_packet:
|
|
db 0x10
|
|
db 0
|
|
.sectors:
|
|
dw 0
|
|
.offset:
|
|
dw 0
|
|
.segment:
|
|
dw 0
|
|
.lba:
|
|
dd 0
|
|
dd 0
|
|
|
|
times 510-($-$$) db 0
|
|
dw 0xAA55
|