~vdupras/duskos

7900d80fd5e30cfa2e35c4294ec0870358147325 — Virgil Dupras a month ago 311c464
fs/boot: we're reading something!
2 files changed, 58 insertions(+), 6 deletions(-)

M fs/fs/boot.fs
M fs/tests/fs/boot.fs
M fs/fs/boot.fs => fs/fs/boot.fs +55 -4
@@ 26,14 26,28 @@ create bpb BPBSZ allot
: FirstDataSector BPB_RsvdSecCnt BPB_NumFATs BPB_FATSz16 * + RootDirSectors + ;
: FirstSectorOfCluster ( n -- sec ) 1- 1- BPB_SecPerClus * FirstDataSector + ;
: FirstRootDirSecNum BPB_RsvdSecCnt BPB_NumFATs BPB_FATSz16 * + ;
: ClusterSize BPB_SecPerClus BPB_BytsPerSec * ;

\ read multiple sectors in buf
: readsectors ( sec u buf -- )
  A>r swap >r swap >A begin ( buf )
    A> over (drv@) A+ drvblksz + next ( buf ) drop r>A ;

create FAT16( BPB_BytsPerSec BPB_FATSz16 * allot
here value )FAT16
: readFAT BPB_RsvdSecCnt BPB_FATSz16 FAT16( readsectors ;

32 const DIRENTRYSZ
11 const FNAMESZ
: DIR_Name ( direntry -- sa sl ) FNAMESZ ;
: DIR_Cluster ( direntry -- cluster ) 26 + w@ ;
: DIR_FileSize ( direntry -- sz ) 28 + @ ;

\ A buffer where dir entries are copied before we search in them. It's big
\ enough to hold the root dir entries. This means that no directory in the FS
\ can have more than BPB_RootEntCnt entries.
create dirbuf( RootDirSectors BPB_BytsPerSec * allot
here const )dirbuf
11 const FNAMESZ
create fnbuf FNAMESZ allot

: upcase ( c -- c ) dup 'a' - 26 < if $df and then ;


@@ 47,9 61,46 @@ create fnbuf FNAMESZ allot
: findindir ( fname -- direntry ) _tofnbuf
  dirbuf( begin ( a )
    dup )dirbuf < while ( a )
    fnbuf over FNAMESZ []= not while ( a ) DIRENTRYSZ + repeat
    fnbuf over DIR_Name []= not while ( a ) DIRENTRYSZ + repeat
    ( success ) else ( not found ) abort" file not found" then ( a ) ;

\ Make the current dir the root
: readroot A>r RootDirSectors >r FirstRootDirSecNum >A dirbuf( begin ( a )
    A> over (drv@) A+ drvblksz + next ( a ) drop r>A ;
: readroot FirstRootDirSecNum RootDirSectors dirbuf( readsectors ;

\ get cluster following this one in the FAT
: nextcluster ( cluster -- nextcluster ) abort" TODO" ;

\ File cursor
\ 2b first cluster
\ 2b current cluster in buf
\ 4b cur pos (offset from beginning of file)
\ 4b file size
\ Xb current cluster X=ClusterSize
4 const FCURSORCNT \ maximum number of opened files
: FCursorSize ClusterSize 12 + ;
: FCUR_cluster0 ( fcur -- n ) w@ ;
: FCUR_cluster ( fcur -- n ) 2 + w@ ;
: FCUR_pos ( fcur -- n ) 4 + @ ;
\ return pos and post-inc it
: FCUR_pos+ ( fcur -- n ) 4 + dup @ 1 rot +! ;
: FCUR_buf( ( fcur -- a ) 12 + ;

create fcursors( FCursorSize FCURSORCNT * allot
here value )fcursor
fcursors( value nextfcursor

: readcluster ( cluster dst -- )
  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 )
  0 nextfcursor 4 + ! DIR_FileSize nextfcursor 8 + ! ( )
  nextfcursor FCursorSize to+ nextfcursor ( fcursor ) ;

: fat16read ( fcursor -- c )
  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"
  then ( fc c ) nip ;

M fs/tests/fs/boot.fs => fs/tests/fs/boot.fs +3 -2
@@ 7,7 7,8 @@
?f<< fs/boot.fs
testbegin
\ Tests for fs/boot
readFAT
readroot
S" init.fs" findindir
FNAMESZ []>str S" INIT    FS " #s=
S" init.fs" findindir ( dirent )
fat16open ( fcursor ) fat16read '\' #eq
testend