Pave way for supporting FAT16 and FAT12
This commit is contained in:
parent
e34accfcff
commit
f46871502c
31
Makefile
31
Makefile
@ -48,20 +48,41 @@ vga11.com: cp437.bin
|
|||||||
%.bs: boot/%.asm
|
%.bs: boot/%.asm
|
||||||
$(NASM) $(NASM_ARGS) -o $@ $<
|
$(NASM) $(NASM_ARGS) -o $@ $<
|
||||||
|
|
||||||
|
# Special case: variations of FAT vbr
|
||||||
|
fat1.bs: boot/fat.asm
|
||||||
|
$(NASM) $(NASM_ARGS) -DFAT12 -DCHS -o $@ $<
|
||||||
|
|
||||||
|
fat4.bs: boot/fat.asm
|
||||||
|
$(NASM) $(NASM_ARGS) -DFAT16 -DCHS -o $@ $<
|
||||||
|
|
||||||
|
fat6.bs: boot/fat.asm
|
||||||
|
$(NASM) $(NASM_ARGS) -DFAT16 -DCHS -DLARGE -o $@ $<
|
||||||
|
|
||||||
|
fatb.bs: boot/fat.asm
|
||||||
|
$(NASM) $(NASM_ARGS) -DFAT32 -DCHS -DLARGE -o $@ $<
|
||||||
|
|
||||||
|
fatc.bs: boot/fat.asm
|
||||||
|
$(NASM) $(NASM_ARGS) -DFAT32 -DLBA -DLARGE -o $@ $<
|
||||||
|
|
||||||
|
fate.bs: boot/fat.asm
|
||||||
|
$(NASM) $(NASM_ARGS) -DFAT16 -DLBA -DLARGE -o $@ $<
|
||||||
|
|
||||||
# BIOS option roms
|
# BIOS option roms
|
||||||
%.rom: rom/%.asm utils/fix-rom
|
%.rom: rom/%.asm utils/fix-rom
|
||||||
$(NASM) $(NASM_ARGS) -o $@ $< && utils/fix-rom $@
|
$(NASM) $(NASM_ARGS) -o $@ $< && utils/fix-rom $@
|
||||||
|
|
||||||
fdimage.img: fat.bs $(DISTFILES)
|
fdimage.img: fat1.bs $(DISTFILES)
|
||||||
mformat -C -i $@ -f $(FLOPPY) -B fat.bs ::
|
mformat -C -i $@ -f $(FLOPPY) -B fat1.bs ::
|
||||||
mcopy -i $@ $(DISTFILES) ::
|
mmd -i $@ ::rdos
|
||||||
|
mcopy -i $@ $(DISTFILES) ::rdos
|
||||||
|
mattrib -i $@ +s ::rdos ::rdos/kernel.bs
|
||||||
|
|
||||||
hdimage.img: mbr.bs fdimage.img
|
hdimage.img: mbr.bs fdimage.img
|
||||||
cat mbr.bs fdimage.img >$@
|
cat mbr.bs fdimage.img >$@
|
||||||
|
|
||||||
part.img: fat32.bs $(DISTFILES)
|
part.img: fatc.bs $(DISTFILES)
|
||||||
dd if=/dev/zero bs=1024 count=33k of=$@
|
dd if=/dev/zero bs=1024 count=33k of=$@
|
||||||
mformat -i $@ -F -B fat32.bs ::
|
mformat -i $@ -F -B fatc.bs ::
|
||||||
mmd -i $@ ::rdos
|
mmd -i $@ ::rdos
|
||||||
mcopy -i $@ $(DISTFILES) ::rdos
|
mcopy -i $@ $(DISTFILES) ::rdos
|
||||||
mattrib -i $@ +s ::rdos ::rdos/kernel.bs
|
mattrib -i $@ +s ::rdos ::rdos/kernel.bs
|
||||||
|
498
boot/fat.asm
498
boot/fat.asm
@ -1,293 +1,289 @@
|
|||||||
; Bootsector for FAT12 filesystems
|
; Bootsector for FAT32 filesystems
|
||||||
; Memory layout:
|
; Takes defines:
|
||||||
; 0000-03FF IVT
|
; FAT12 FAT has 1.5 bytes per entry
|
||||||
; 0400-0500 Bios data area
|
; FAT16 FAT has WORD per entry
|
||||||
; 0501-0600 Stack for us
|
; FAT32 FAT has DWORD per entry
|
||||||
; 0600-0800 This code
|
; CHS uses int13h/AH=02h
|
||||||
org 0x0600
|
; LARGE requires 32 bit sector numbers
|
||||||
; 0800-0A00 Buffer for disk
|
; LBA uses int13h/AH=42h
|
||||||
buf: equ 0x0800
|
cpu 8086
|
||||||
|
|
||||||
jmp near init
|
org 0x0800
|
||||||
|
jmp short init
|
||||||
|
nop
|
||||||
|
|
||||||
; current cluster number
|
%include "inc/bpb.asm"
|
||||||
cclus: dw 0
|
|
||||||
; sector number in cluster
|
|
||||||
csec: dw 0
|
|
||||||
|
|
||||||
times (0x0B - ($-$$)) db 0
|
bpb: equ 0x080B
|
||||||
; BIOS PARAMETER BLOCK
|
|
||||||
fdc: ; sector size
|
|
||||||
.ss: dw 0x200
|
|
||||||
; sectors per cluster
|
|
||||||
.sc: db 2
|
|
||||||
; reserved sector count
|
|
||||||
.rsc: dw 1
|
|
||||||
.fn: ; number of file allocation tables
|
|
||||||
db 2
|
|
||||||
.rde: ; number of root directory entries
|
|
||||||
dw 0x70
|
|
||||||
.ts: ; total number of sectors
|
|
||||||
dw 720
|
|
||||||
.mid: db 0xFD
|
|
||||||
.sf: dw 2
|
|
||||||
.spt: dw 9
|
|
||||||
.nos: dw 2
|
|
||||||
.po: dd 0
|
|
||||||
.lrgts: ; large sector count - relevant if .ts is 0
|
|
||||||
dd 0
|
|
||||||
|
|
||||||
; mformat keeps writing until here
|
; Area for BPB
|
||||||
; if we place init earlier, code gets overwritten
|
times ( 0x5A - ($-$$) ) db 0
|
||||||
; this also marks the end for the BPB
|
|
||||||
times (62 - ($-$$)) nop
|
|
||||||
|
|
||||||
init: xor ax, ax
|
init: xor ax, ax
|
||||||
|
mov ss, ax
|
||||||
|
mov sp, 0x7C00
|
||||||
|
|
||||||
|
; save potential partition table entry
|
||||||
|
push ds
|
||||||
|
push si
|
||||||
|
|
||||||
mov ds, ax
|
mov ds, ax
|
||||||
mov es, ax
|
mov es, ax
|
||||||
mov ss, ax
|
|
||||||
mov sp, 0x0600
|
|
||||||
|
|
||||||
; Relocate and jump
|
|
||||||
mov di, sp
|
|
||||||
mov si, 0x7C00
|
mov si, 0x7C00
|
||||||
|
mov di, 0x0800
|
||||||
mov cx, 0x0100
|
mov cx, 0x0100
|
||||||
rep movsw
|
rep movsw
|
||||||
jmp 0:main
|
jmp 0x0:main
|
||||||
|
|
||||||
; Set adress for sector read/write
|
%include "inc/booterr.asm"
|
||||||
; Number is relative to current partition
|
|
||||||
; IN dx:ax sector number
|
|
||||||
seek: push ax
|
|
||||||
push dx
|
|
||||||
push ds
|
|
||||||
push cs
|
|
||||||
pop ds
|
|
||||||
; add partition offset (required for HDD)
|
|
||||||
add ax, [fdc.po]
|
|
||||||
adc dx, [fdc.po+2]
|
|
||||||
; ax:temp = (lba / spt)
|
|
||||||
; dx:sector = (lba % spt) + 1
|
|
||||||
div word [fdc.spt]
|
|
||||||
inc dx
|
|
||||||
; Sector number (bits 0-5) into CL
|
|
||||||
; This is blindly assumed to never exeed 63
|
|
||||||
mov byte [.cl], dl
|
|
||||||
; ax:cylinder = (tmp / heads)
|
|
||||||
; dx:head = (tmp % heads)
|
|
||||||
xor dx, dx
|
|
||||||
div word [fdc.nos]
|
|
||||||
; Cylinder number bit 0-7 into CH
|
|
||||||
mov byte [.ch], al
|
|
||||||
; Head number into DL
|
|
||||||
mov byte [.dh], dl
|
|
||||||
; Bits 8-9 of cylinder number into bits 6-7 of CL
|
|
||||||
and ah, 0x03
|
|
||||||
ror ah, 1
|
|
||||||
ror ah, 1
|
|
||||||
or byte [.cl], ah
|
|
||||||
pop ds
|
|
||||||
pop dx
|
|
||||||
pop ax
|
|
||||||
ret
|
|
||||||
.cl: db 0
|
|
||||||
.ch: db 0
|
|
||||||
.dl: db 0
|
|
||||||
.dh: db 0
|
|
||||||
|
|
||||||
; Read sector into ES:BX
|
; offsets relative to FS
|
||||||
; Sector number has been previously set with seek
|
readd: ; add offset of cluster data area to DX:AX
|
||||||
read: push ax
|
|
||||||
push cx
|
push cx
|
||||||
push dx
|
mov di, [bp+bpb_rde]
|
||||||
; ah = int13 subfunction 2
|
|
||||||
; al = read 1 sector
|
|
||||||
mov ax, 0x0201
|
|
||||||
; load seek data into registers
|
|
||||||
mov cx, word [cs:seek.cl]
|
|
||||||
mov dx, word [cs:seek.dl]
|
|
||||||
|
|
||||||
int 0x13
|
|
||||||
int 3
|
|
||||||
|
|
||||||
pop dx
|
|
||||||
pop cx
|
|
||||||
pop ax
|
|
||||||
ret
|
|
||||||
|
|
||||||
; Get start sector of root dirrectory
|
|
||||||
; OUT ax sector number
|
|
||||||
dirsec: ; Multiply sectors per fat with number of fats
|
|
||||||
mov ax, [cs:fdc.sf]
|
|
||||||
mul byte [cs:fdc.fn]
|
|
||||||
; Add number of reserved sectors
|
|
||||||
add ax, [cs:fdc.rsc]
|
|
||||||
ret
|
|
||||||
|
|
||||||
; Get root directory length in sectors
|
|
||||||
; OUT cx sectors
|
|
||||||
dirlen: push ax
|
|
||||||
mov ax, [cs:fdc.rde]
|
|
||||||
mov cl, 4
|
mov cl, 4
|
||||||
shr ax, cl ; 32 bytes per entry
|
shr di, cl ; 32 bytes per entry
|
||||||
mov cx, ax
|
add ax, di
|
||||||
pop ax
|
adc dx, 0
|
||||||
ret
|
|
||||||
|
|
||||||
; Get first sector of data area
|
|
||||||
; OUT ax sector number
|
|
||||||
clusec: push cx
|
|
||||||
call dirsec
|
|
||||||
call dirlen
|
|
||||||
add ax, cx
|
|
||||||
pop cx
|
pop cx
|
||||||
ret: ret
|
readr: ; add offset to rootdir to DX:AX (FAT12/FAT16 only)
|
||||||
|
|
||||||
; Get total number of sectors
|
|
||||||
; OUT: dx:ax number of sectors
|
|
||||||
secnum: xor dx, dx
|
|
||||||
mov ax, [cs:fdc.ts]
|
|
||||||
test ax, ax
|
|
||||||
jnz ret
|
|
||||||
mov ax, [cs:fdc.lrgts]
|
|
||||||
mov dx, [cs:fdc.lrgts+2]
|
|
||||||
ret
|
|
||||||
|
|
||||||
; Get number of clusters
|
|
||||||
; OUT: ax number of clusters
|
|
||||||
; Cant overflow for FAT16 :P
|
|
||||||
clunum: push cx
|
|
||||||
push dx
|
|
||||||
call clusec
|
|
||||||
mov cx, ax
|
|
||||||
call secnum
|
|
||||||
sub ax, cx
|
|
||||||
sbb dx, 0
|
|
||||||
mov cl, byte [cs:fdc.sc]
|
|
||||||
xor ch, ch
|
|
||||||
div cx
|
|
||||||
pop dx
|
|
||||||
pop cx
|
|
||||||
ret
|
|
||||||
|
|
||||||
; Scan current buffer for matching file
|
|
||||||
; IN ds = cs
|
|
||||||
; es = cs
|
|
||||||
; OUT bx start cluster if file found
|
|
||||||
; trashed if no match
|
|
||||||
; carry is set if no file was found
|
|
||||||
scadir:
|
|
||||||
push cx
|
push cx
|
||||||
push si
|
xor ch, ch
|
||||||
mov si, buf
|
mov cl, byte [bp+bpb_fn]
|
||||||
mov cx, 0x10
|
fatlp: add ax, [bp+bpb7_lsf]
|
||||||
.loop: push cx
|
adc dx, [bp+bpb7_lsf+2]
|
||||||
push si
|
loop fatlp
|
||||||
mov bx, [si+0x1A]
|
|
||||||
mov di, .name
|
|
||||||
mov cx, 11
|
|
||||||
repe cmpsb
|
|
||||||
pop si
|
|
||||||
pop cx
|
pop cx
|
||||||
je .found
|
readf: ; add offset to FAT table to DX:AX
|
||||||
add si, 0x20
|
add ax, word [bp+bpb_rsc]
|
||||||
loop .loop
|
adc dx, 0
|
||||||
stc
|
readp: ; read sector DX:AX from partition
|
||||||
.found: pop si
|
add ax, word [bp+bpb_po]
|
||||||
pop cx
|
adc dx, word [bp+bpb_po+2]
|
||||||
ret
|
jnc ($+5)
|
||||||
.name: db "HELLO "
|
call errcll
|
||||||
.ext: db "COM"
|
|
||||||
|
|
||||||
fopen:
|
%ifdef LBA
|
||||||
|
read_: ; read sector DX:AX from disk
|
||||||
|
; this uses the EBIOS extensions
|
||||||
|
; qword sector number DX:AX
|
||||||
|
push cs
|
||||||
|
push cs
|
||||||
|
push dx
|
||||||
push ax
|
push ax
|
||||||
|
|
||||||
|
; dword target buffer: BX:0
|
||||||
|
push bx
|
||||||
|
push cs
|
||||||
|
|
||||||
|
; word sector number
|
||||||
|
push cx
|
||||||
|
|
||||||
|
; size & passing
|
||||||
|
mov di, 0x10
|
||||||
|
push di
|
||||||
|
|
||||||
|
mov si, sp
|
||||||
|
mov ah, 0x42
|
||||||
|
mov dl, [bp+bpb7_dn]
|
||||||
|
stc
|
||||||
|
int 0x13
|
||||||
|
jnc ($+5)
|
||||||
|
call errcll
|
||||||
|
|
||||||
|
add sp, di
|
||||||
|
|
||||||
|
ret
|
||||||
|
%endif
|
||||||
|
|
||||||
|
%ifdef CHS
|
||||||
|
read_: ; read sector DX:AX from disk
|
||||||
|
; uses basic CHS disk IO
|
||||||
|
; this cant reliable read over track boundaries
|
||||||
|
; so we read each single sector in loop over CX
|
||||||
|
chslp: push ax
|
||||||
push cx
|
push cx
|
||||||
push dx
|
push dx
|
||||||
push bx
|
push bx
|
||||||
push ds
|
|
||||||
push es
|
; calculate CHS data
|
||||||
cmp word [cclus], 0
|
div word [bp+bpb_spt] ; ax:temp = (lba / spt)
|
||||||
jne .err
|
inc dx ; dx:sector = (lba % spt) + 1
|
||||||
xor ax, ax
|
mov cl, dl ; sector number
|
||||||
mov ds, ax
|
xor dx, dx
|
||||||
mov es, ax
|
div word [bp+bpb_nos] ; ax:cylinder = (tmp / heads)
|
||||||
call dirsec
|
; dx:head = (tmp % heads)
|
||||||
call dirlen
|
mov ch, al ; cylinder number
|
||||||
.loop: xor dx, dx
|
mov dh, dl ; head number
|
||||||
mov bx, buf
|
mov dl, [bp+bpb7_dn] ; drive number
|
||||||
call seek
|
|
||||||
call read
|
; set up read buffer
|
||||||
call scadir
|
mov es, bx
|
||||||
jnc .found
|
xor bx, bx
|
||||||
inc ax
|
|
||||||
loop .loop
|
; call bios
|
||||||
.err: stc
|
mov ax, 0x0201
|
||||||
jmp .ret
|
int 0x13
|
||||||
.found: mov [cclus], bx
|
jnc ($+5)
|
||||||
mov word [csec], 0
|
call errcll
|
||||||
.ret: pop es
|
|
||||||
pop ds
|
|
||||||
pop bx
|
pop bx
|
||||||
pop dx
|
pop dx
|
||||||
pop cx
|
pop cx
|
||||||
pop ax
|
pop ax
|
||||||
ret
|
|
||||||
|
|
||||||
fread: push ax
|
; increment sector num + write offset
|
||||||
push cx
|
add ax, 1
|
||||||
push dx
|
|
||||||
; abort if there is no file opened
|
|
||||||
cmp word [cs:cclus], 0
|
|
||||||
je .err
|
|
||||||
; get start sector for data area
|
|
||||||
call clusec
|
|
||||||
push ax
|
|
||||||
; get current cluster number
|
|
||||||
mov ax, [cs:cclus]
|
|
||||||
; clusters are 2-indexed
|
|
||||||
sub ax, 2
|
|
||||||
; multiply that with sectors per cluster
|
|
||||||
mov cl, [cs:fdc.sc]
|
|
||||||
xor ch, ch
|
|
||||||
mul word cx
|
|
||||||
; add current cluster offset, cluster start and current sector
|
|
||||||
pop cx
|
|
||||||
add cx, [cs:csec]
|
|
||||||
add ax, cx
|
|
||||||
adc dx, 0
|
adc dx, 0
|
||||||
; dx:ax now point to the sector that should be read next
|
add bx, 0x20
|
||||||
call seek
|
; loop on CX
|
||||||
call read
|
loop chslp
|
||||||
jc .err
|
ret
|
||||||
inc word [cs:csec]
|
%endif
|
||||||
jmp .ret
|
|
||||||
.err: ; in case of error, trash current state
|
next: ; Advances DX:AX to next FAT entry
|
||||||
call fclose
|
push ax
|
||||||
stc
|
push bx
|
||||||
.ret: pop dx
|
; shift 2 left for dword-sized FAT entries
|
||||||
pop cx
|
; shift 9 right for sector size
|
||||||
|
mov cl, 7
|
||||||
|
shftl: clc
|
||||||
|
rcr dx, 1
|
||||||
|
rcr ax, 1
|
||||||
|
loop shftl
|
||||||
|
|
||||||
|
mov bx, 0xA0
|
||||||
|
%ifdef FAT12
|
||||||
|
; FAT item might span over two sectors
|
||||||
|
mov cx, 2
|
||||||
|
%else
|
||||||
|
mov cx, 1
|
||||||
|
%endif
|
||||||
|
call readf
|
||||||
|
|
||||||
|
pop bx
|
||||||
|
|
||||||
|
; get lower part of cluster number
|
||||||
|
pop si
|
||||||
|
%ifdef FAT16
|
||||||
|
; double
|
||||||
|
sal si, 1
|
||||||
|
%endif
|
||||||
|
%ifdef FAT32
|
||||||
|
; multiply with 4
|
||||||
|
sal si, 1
|
||||||
|
sal si, 1
|
||||||
|
%endif
|
||||||
|
; make sure its within sector range
|
||||||
|
and si, 0x1FF
|
||||||
|
add si, buf
|
||||||
|
%ifdef FAT16
|
||||||
|
; load word from FAT
|
||||||
|
lodsw
|
||||||
|
xor dx, dx
|
||||||
|
%endif
|
||||||
|
%ifdef FAT32
|
||||||
|
; load dword from FAT
|
||||||
|
lodsw
|
||||||
|
mov dx, [si]
|
||||||
|
%endif
|
||||||
|
ret
|
||||||
|
|
||||||
|
; reads current cluster into [dest]
|
||||||
|
readc: ; load cluster number
|
||||||
|
push ax
|
||||||
|
push dx
|
||||||
|
|
||||||
|
; subtract the two dummy entries from FAT start
|
||||||
|
sub ax, 2
|
||||||
|
sbb dx, 0
|
||||||
|
|
||||||
|
; convert cluster number to sector number
|
||||||
|
; this is some cheapo multiplication with 2^n
|
||||||
|
mov cl, [bp+bpb_sc]
|
||||||
|
l02: shr cl, 1
|
||||||
|
jz l02e
|
||||||
|
clc
|
||||||
|
rcl ax, 1
|
||||||
|
rcl dx, 1
|
||||||
|
jmp l02
|
||||||
|
l02e:
|
||||||
|
; dx:ax is now sector num in data area
|
||||||
|
mov cx, [bp+bpb_sc]
|
||||||
|
xor ch, ch
|
||||||
|
|
||||||
|
call readd
|
||||||
|
|
||||||
|
xchg di, cx
|
||||||
|
mov cl, 5
|
||||||
|
sal di, cl
|
||||||
|
add bx, di
|
||||||
|
|
||||||
|
pop dx
|
||||||
pop ax
|
pop ax
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; Reset open file info
|
; Load root directory
|
||||||
fclose: mov [cclus], bx
|
loadr: mov ax, 2
|
||||||
mov word [csec], 0
|
xor dx, dx
|
||||||
|
jmp load
|
||||||
|
|
||||||
|
; Load file identified by fsattr
|
||||||
|
; Directory data is expected at 0x07C00
|
||||||
|
loadf: mov si, (0x7C00-0x20)
|
||||||
|
sloop: add si, 0x20
|
||||||
|
; check if entry is valid
|
||||||
|
mov al, [si]
|
||||||
|
; unallocated direntry
|
||||||
|
test al, al
|
||||||
|
jnz ($+5)
|
||||||
|
call errcll
|
||||||
|
; deleted files
|
||||||
|
cmp al, 0xE2
|
||||||
|
je sloop
|
||||||
|
; check attr
|
||||||
|
mov al, [si+11]
|
||||||
|
and al, 0x5C
|
||||||
|
cmp al, ah
|
||||||
|
jne sloop
|
||||||
|
mov ax, [si+0x1A]
|
||||||
|
mov dx, [si+0x14]
|
||||||
|
|
||||||
|
; Load cluster chain DX:AX to 0x07C00
|
||||||
|
load: mov bx, 0x07C0
|
||||||
|
lloop: call readc
|
||||||
|
call next
|
||||||
|
cmp word dx, 0x0FFF
|
||||||
|
jne lloop
|
||||||
ret
|
ret
|
||||||
|
|
||||||
main: mov [seek.dl], dl ; save drive number
|
main: ; Set up BP to point to BPB
|
||||||
|
; Relative addressing saves one instruction byte per access
|
||||||
|
mov bp, bpb
|
||||||
|
; Save DL contents
|
||||||
|
mov [bp+bpb7_dn], dl
|
||||||
|
|
||||||
call fopen
|
; load root directory
|
||||||
mov bx, 0x1100
|
call loadr
|
||||||
call fread
|
; search for first system directory
|
||||||
|
mov ah, 0x14
|
||||||
|
call loadf
|
||||||
|
; search for first system file
|
||||||
|
mov ah, 0x04
|
||||||
|
call loadf
|
||||||
|
|
||||||
mov ax, 0x0100
|
; restore drive number
|
||||||
mov ds, ax
|
mov dl, [bp+bpb7_dn]
|
||||||
mov es, ax
|
|
||||||
call 0x100:0x100
|
|
||||||
|
|
||||||
.hlt: hlt
|
; restore potential partition table
|
||||||
jmp .hlt
|
pop si
|
||||||
|
pop ds
|
||||||
|
|
||||||
|
jmp 0x7C00
|
||||||
|
|
||||||
; Padding and signature
|
; Padding and signature
|
||||||
times (0x1FE - ($-$$)) db 0
|
times (0x1FE - ($-$$)) db 0
|
||||||
dw 0xAA55
|
dw 0xAA55
|
||||||
|
buf:
|
||||||
|
281
boot/fat32.asm
281
boot/fat32.asm
@ -1,281 +0,0 @@
|
|||||||
; Bootsector for FAT32 filesystems
|
|
||||||
org 0x0800
|
|
||||||
cpu 8086
|
|
||||||
jmp short init
|
|
||||||
nop
|
|
||||||
|
|
||||||
%include "inc/bpb.asm"
|
|
||||||
|
|
||||||
bpb: equ 0x080B
|
|
||||||
|
|
||||||
; Area for BPB
|
|
||||||
times ( 0x5A - ($-$$) ) db 0
|
|
||||||
|
|
||||||
init: xor ax, ax
|
|
||||||
mov ss, ax
|
|
||||||
mov sp, 0x7C00
|
|
||||||
|
|
||||||
; save potential partition table entry
|
|
||||||
push ds
|
|
||||||
push si
|
|
||||||
|
|
||||||
mov ds, ax
|
|
||||||
mov es, ax
|
|
||||||
|
|
||||||
mov si, 0x7C00
|
|
||||||
mov di, 0x0800
|
|
||||||
mov cx, 0x0100
|
|
||||||
rep movsw
|
|
||||||
jmp 0x0:main
|
|
||||||
|
|
||||||
%include "inc/booterr.asm"
|
|
||||||
|
|
||||||
; offsets relative to FS
|
|
||||||
readd: ; add offset of cluster data area to DX:AX
|
|
||||||
push cx
|
|
||||||
mov di, [bp+bpb_rde]
|
|
||||||
mov cl, 4
|
|
||||||
shr di, cl ; 32 bytes per entry
|
|
||||||
add ax, di
|
|
||||||
adc dx, 0
|
|
||||||
pop cx
|
|
||||||
readr: ; add offset to rootdir to DX:AX (FAT12/FAT16 only)
|
|
||||||
push cx
|
|
||||||
xor ch, ch
|
|
||||||
mov cl, byte [bp+bpb_fn]
|
|
||||||
fatlp: add ax, [bp+bpb7_lsf]
|
|
||||||
adc dx, [bp+bpb7_lsf+2]
|
|
||||||
loop fatlp
|
|
||||||
pop cx
|
|
||||||
readf: ; add offset to FAT table to DX:AX
|
|
||||||
add ax, word [bp+bpb_rsc]
|
|
||||||
adc dx, 0
|
|
||||||
readp: ; read sector DX:AX from partition
|
|
||||||
add ax, word [bp+bpb_po]
|
|
||||||
adc dx, word [bp+bpb_po+2]
|
|
||||||
jc dskerr
|
|
||||||
|
|
||||||
; This jump is overwritten with NOP's if LBA support
|
|
||||||
dskjmp: jmp rchs
|
|
||||||
|
|
||||||
rebios: ; read sector DX:AX from disk
|
|
||||||
; this uses the EBIOS extensions
|
|
||||||
; qword sector number DX:AX
|
|
||||||
push cs
|
|
||||||
push cs
|
|
||||||
push dx
|
|
||||||
push ax
|
|
||||||
|
|
||||||
; dword target buffer: BX:0
|
|
||||||
push bx
|
|
||||||
push cs
|
|
||||||
|
|
||||||
; word sector number
|
|
||||||
push cx
|
|
||||||
|
|
||||||
; size & passing
|
|
||||||
mov di, 0x10
|
|
||||||
push di
|
|
||||||
|
|
||||||
mov si, sp
|
|
||||||
mov ah, 0x42
|
|
||||||
mov dl, [bp+bpb7_dn]
|
|
||||||
stc
|
|
||||||
int 0x13
|
|
||||||
jc dskerr
|
|
||||||
|
|
||||||
add sp, di
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
rchs: ; read sector DX:AX from disk
|
|
||||||
; uses basic CHS disk IO
|
|
||||||
; this cant reliable read over track boundaries
|
|
||||||
; so we read each single sector in loop over CX
|
|
||||||
chslp: push ax
|
|
||||||
push cx
|
|
||||||
push dx
|
|
||||||
push bx
|
|
||||||
|
|
||||||
; calculate CHS data
|
|
||||||
div word [bp+bpb_spt] ; ax:temp = (lba / spt)
|
|
||||||
inc dx ; dx:sector = (lba % spt) + 1
|
|
||||||
mov cl, dl ; sector number
|
|
||||||
xor dx, dx
|
|
||||||
div word [bp+bpb_nos] ; ax:cylinder = (tmp / heads)
|
|
||||||
; dx:head = (tmp % heads)
|
|
||||||
mov ch, al ; cylinder number
|
|
||||||
mov dh, dl ; head number
|
|
||||||
mov dl, [bp+bpb7_dn] ; drive number
|
|
||||||
|
|
||||||
; set up read buffer
|
|
||||||
mov es, bx
|
|
||||||
xor bx, bx
|
|
||||||
|
|
||||||
; call bios
|
|
||||||
mov ax, 0x0201
|
|
||||||
int 0x13
|
|
||||||
jc dskerr
|
|
||||||
|
|
||||||
pop bx
|
|
||||||
pop dx
|
|
||||||
pop cx
|
|
||||||
pop ax
|
|
||||||
|
|
||||||
; increment sector num + write offset
|
|
||||||
add ax, 1
|
|
||||||
adc dx, 0
|
|
||||||
add bx, 0x20
|
|
||||||
; loop on CX
|
|
||||||
loop chslp
|
|
||||||
ret
|
|
||||||
|
|
||||||
; error handling for disk errors
|
|
||||||
dskerr: call errcll
|
|
||||||
|
|
||||||
next: ; Advances DX:AX to next FAT entry
|
|
||||||
push ax
|
|
||||||
push bx
|
|
||||||
|
|
||||||
; shift 2 left for dword-sized FAT entries
|
|
||||||
; shift 9 right for sector size
|
|
||||||
mov cl, 7
|
|
||||||
shftl: clc
|
|
||||||
rcr dx, 1
|
|
||||||
rcr ax, 1
|
|
||||||
loop shftl
|
|
||||||
|
|
||||||
mov bx, 0xA0
|
|
||||||
mov cx, 1
|
|
||||||
call readf
|
|
||||||
|
|
||||||
pop bx
|
|
||||||
|
|
||||||
; get lower part of cluster number
|
|
||||||
pop si
|
|
||||||
; multiply with 4
|
|
||||||
sal si, 1
|
|
||||||
sal si, 1
|
|
||||||
; make sure its within sector range
|
|
||||||
and si, 0x1FF
|
|
||||||
add si, buf
|
|
||||||
; load dword from FAT
|
|
||||||
lodsw
|
|
||||||
mov dx, [si]
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
; reads current cluster into [dest]
|
|
||||||
readc: ; load cluster number
|
|
||||||
push ax
|
|
||||||
push dx
|
|
||||||
|
|
||||||
; subtract the two dummy entries from FAT start
|
|
||||||
sub ax, 2
|
|
||||||
sbb dx, 0
|
|
||||||
|
|
||||||
; convert cluster number to sector number
|
|
||||||
; this is some cheapo multiplication with 2^n
|
|
||||||
mov cl, [bp+bpb_sc]
|
|
||||||
l02: shr cl, 1
|
|
||||||
jz l02e
|
|
||||||
clc
|
|
||||||
rcl ax, 1
|
|
||||||
rcl dx, 1
|
|
||||||
jmp l02
|
|
||||||
l02e:
|
|
||||||
; dx:ax is now sector num in data area
|
|
||||||
mov cx, [bp+bpb_sc]
|
|
||||||
xor ch, ch
|
|
||||||
|
|
||||||
call readd
|
|
||||||
|
|
||||||
xchg di, cx
|
|
||||||
mov cl, 5
|
|
||||||
sal di, cl
|
|
||||||
add bx, di
|
|
||||||
|
|
||||||
pop dx
|
|
||||||
pop ax
|
|
||||||
|
|
||||||
ret
|
|
||||||
|
|
||||||
; Load root directory
|
|
||||||
loadr: mov ax, 2
|
|
||||||
xor dx, dx
|
|
||||||
jmp load
|
|
||||||
|
|
||||||
; Load file identified by fsattr
|
|
||||||
; Directory data is expected at 0x07C00
|
|
||||||
loadf: mov si, (0x7C00-0x20)
|
|
||||||
sloop: add si, 0x20
|
|
||||||
; check if entry is valid
|
|
||||||
mov al, [si]
|
|
||||||
; unallocated direntry
|
|
||||||
test al, al
|
|
||||||
jz fserr
|
|
||||||
; deleted files
|
|
||||||
cmp al, 0xE2
|
|
||||||
je sloop
|
|
||||||
; check attr
|
|
||||||
mov al, [si+11]
|
|
||||||
and al, 0x5C
|
|
||||||
cmp al, ah
|
|
||||||
jne sloop
|
|
||||||
mov ax, [si+0x1A]
|
|
||||||
mov dx, [si+0x14]
|
|
||||||
|
|
||||||
; Load cluster chain DX:AX to 0x07C00
|
|
||||||
load: mov bx, 0x07C0
|
|
||||||
lloop: call readc
|
|
||||||
call next
|
|
||||||
cmp word dx, 0x0FFF
|
|
||||||
jne lloop
|
|
||||||
ret
|
|
||||||
|
|
||||||
main: ; Set up BP to point to BPB
|
|
||||||
; Relative addressing saves one instruction byte per access
|
|
||||||
mov bp, bpb
|
|
||||||
; Save DL contents
|
|
||||||
mov [bp+bpb7_dn], dl
|
|
||||||
|
|
||||||
; EBIOS is ignored for floppies (dl < 80h)
|
|
||||||
test dl, 0x80
|
|
||||||
jz noebio
|
|
||||||
|
|
||||||
; check for EBIOS support
|
|
||||||
mov bx, 0x55AA
|
|
||||||
mov ah, 0x41
|
|
||||||
; set carry to assume failure if int didnt do anything
|
|
||||||
stc
|
|
||||||
int 0x13
|
|
||||||
jc noebio
|
|
||||||
|
|
||||||
; disable CHS routine, fall into LBA routine instead
|
|
||||||
mov word [dskjmp], 0x9090
|
|
||||||
|
|
||||||
noebio: ; load root directory
|
|
||||||
call loadr
|
|
||||||
; search for first system directory
|
|
||||||
mov ah, 0x14
|
|
||||||
call loadf
|
|
||||||
; search for first system file
|
|
||||||
mov ah, 0x04
|
|
||||||
call loadf
|
|
||||||
|
|
||||||
; restore drive number
|
|
||||||
mov dl, [bp+bpb7_dn]
|
|
||||||
|
|
||||||
; restore potential partition table
|
|
||||||
pop si
|
|
||||||
pop ds
|
|
||||||
|
|
||||||
jmp 0x7C00
|
|
||||||
|
|
||||||
; error handling for file not found
|
|
||||||
fserr: call errcll
|
|
||||||
|
|
||||||
; Padding and signature
|
|
||||||
times (0x1FE - ($-$$)) db 0
|
|
||||||
dw 0xAA55
|
|
||||||
buf:
|
|
Loading…
Reference in New Issue
Block a user