commit c020600131c8400cac2bb523cde2025817111586
parent 1024013264e4d4ce43099f4e2a4de4670c8191fb
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Fri, 1 Jul 2022 09:14:21 -0400
fs/boot: support files with multiple clusters
Diffstat:
3 files changed, 25 insertions(+), 7 deletions(-)
diff --git a/fs/fattest b/fs/fattest
Binary files differ.
diff --git a/fs/fs/boot.fs b/fs/fs/boot.fs
@@ -3,7 +3,7 @@
\ This is a subset of a FAT16 implementation. It is designed to be embedded
\ right after "boot.fs" and provide the means to continue bootstrapping on.
-\ Its goal is to provide fopen and fread, nothing more. The rest of the FAT16
+\ Its goal is to provide fopen and fgetc, nothing more. The rest of the FAT16
\ implementation is in fs/fat16.
\ This unit has access to a very small set of words, that it, words implemented
@@ -67,8 +67,10 @@ create fnbuf FNAMESZ allot
\ Make the current dir the root
: readroot FirstRootDirSecNum RootDirSectors dirbuf( readsectors ;
+: endofclusters? ( cluster -- f ) $ffff = ;
+
\ get cluster following this one in the FAT
-: nextcluster ( cluster -- nextcluster ) abort" TODO" ;
+: nextcluster ( cluster -- nextcluster ) << FAT16( + w@ ;
\ File cursor
\ 2b first cluster
@@ -80,9 +82,11 @@ create fnbuf FNAMESZ allot
: FCursorSize ClusterSize 12 + ;
: FCUR_cluster0 ( fcur -- n ) w@ ;
: FCUR_cluster ( fcur -- n ) 2 + w@ ;
+: FCUR_cluster! ( n fcur -- ) 2 + w! ;
: FCUR_pos ( fcur -- n ) 4 + @ ;
\ return pos and post-inc it
: FCUR_pos+ ( fcur -- n ) 4 + dup @ 1 rot +! ;
+: FCUR_size ( fcur -- n ) 8 + @ ;
: FCUR_buf( ( fcur -- a ) 12 + ;
create fcursors( FCursorSize FCURSORCNT * allot
@@ -90,17 +94,23 @@ here value )fcursor
fcursors( value nextfcursor
: readcluster ( cluster dst -- )
+ over << BPB_BytsPerSec BPB_FATSz16 * >= if abort" cluster out of range" then
swap FirstSectorOfCluster ( dst sec ) swap BPB_SecPerClus swap readsectors ;
: fat16open ( direntry -- fcursor )
nextfcursor )fcursor = if abort" out of file cursors!" then
dup DIR_Cluster ( dirent cluster ) dup nextfcursor FCUR_buf( readcluster
- ( dirent cluster ) dup nextfcursor w! nextfcursor 2 + w! ( dirent )
+ ( dirent cluster ) dup nextfcursor w! nextfcursor FCUR_cluster! ( dirent )
0 nextfcursor 4 + ! DIR_FileSize nextfcursor 8 + ! ( )
nextfcursor FCursorSize to+ nextfcursor ( fcursor ) ;
-: fat16read ( fcursor -- c )
+: fat16getc ( fcursor -- c-or-0 )
+ dup FCUR_pos over FCUR_size = if drop 0 exit then
dup FCUR_pos+ ClusterSize mod over FCUR_buf( + c@ ( fc c )
over FCUR_pos ClusterSize mod not if ( fc c ) \ end of cluster, read next
- abort" TODO"
+ over FCUR_cluster nextcluster ( fc c cluster )
+ dup endofclusters? if drop else
+ dup 2 < if abort" cluster out of range" then
+ rot 2dup FCUR_cluster! ( c cluster fc )
+ tuck FCUR_buf( readcluster ( c fc ) swap then
then ( fc c ) nip ;
diff --git a/fs/tests/fs/boot.fs b/fs/tests/fs/boot.fs
@@ -5,10 +5,18 @@
\ 4. It has a 512 sector size
?f<< tests/harness.fs
?f<< fs/boot.fs
+: readN ( fcursor n -- ) >r begin dup fat16getc drop next drop ;
testbegin
\ Tests for fs/boot
readFAT
readroot
-S" init.fs" findindir ( dirent )
-fat16open ( fcursor ) fat16read '\' #eq
+S" fattest" findindir ( dirent )
+fat16open ( fcursor ) dup fat16getc 'T' #eq
+dup $ff readN ( fcursor )
+dup fat16getc 'f' #eq dup fat16getc 'o' #eq dup fat16getc 'o' #eq
+dup $fd readN ( fcursor )
+dup fat16getc 'b' #eq
+dup $dfc readN ( fcursor )
+dup fat16getc 'E' #eq dup fat16getc 'O' #eq dup fat16getc 'F' #eq
+fat16getc 0 #eq
testend