~vdupras/duskos

50af07158cfa2a6c2c768f4d290847821a4e45c5 — Virgil Dupras 18 days ago 3eaeea4
fs/fat: consolidate
5 files changed, 51 insertions(+), 53 deletions(-)

M fs/doc/lib/drive.txt
M fs/fs/fat.fs
M fs/fs/fatlo.fs
M fs/lib/drivelo.fs
M fs/xcomp/i386/pc/init.fs
M fs/doc/lib/drive.txt => fs/doc/lib/drive.txt +3 -0
@@ 62,6 62,9 @@ Words:
  Move window to "fsec" with "cnt" sectors. This doesn't change or flush the
  current buffer.

:fulldrv ( self -- )
  Move the window so that it spans the whole drive.

:load ( sec self -- )
  Load sector "sec" in the buffer. Aborts if outside the window.


M fs/fs/fat.fs => fs/fs/fat.fs +29 -35
@@ 100,8 100,8 @@ $e5 const DIRFREE
  else nip then rdrop ;

\ try to find in current buffer
: _findinsec ( self -- a-or-0 ) >r
  r@ :dirwin :buf( begin ( a )
: _findinsec ( self -- a-or-0 )
  r! :dirwin :buf( begin ( a ) \ V1=self
    dup c@ dup DIRFREE = swap not or if ( free! ) rdrop exit then
    DirEntry SZ + dup r@ :dirwin :)buf >= until rdrop drop 0 ;



@@ 126,26 126,24 @@ $e5 const DIRFREE

: _makedir ( dirent -- dirent ) $10 over to DirEntry attr ;

0 value _self 0 value _cluster 0 value _parentcl
: fatnewdir ( dirid name self -- id ) to _self
  _self allocatecluster0 to _cluster ( dirid name )
  _self _newentry ( dirent ) _makedir ( dirent )
  _cluster over to DirEntry cluster _self writecursector ( dirent )
  _self :getid ( id ) _self bufcluster to _parentcl
: fatnewdir ( dirid name self -- id )
  r! allocatecluster0 >r ( dirid name ) \ V1=self V2=cluster
  V1 _newentry ( dirent ) _makedir ( dirent )
  V2 over to DirEntry cluster V1 writecursector ( dirent )
  V1 :getid ( id ) V1 bufcluster >r \ V3=parentcl
  \ Cluster allocated, now let's initialize it with "." and ".."
  _cluster _self :FirstSectorOfCluster 1 _self :readsector
  _self :dirwin :buf( dup DirEntry NAMESZ SPC fill '.' over c! _makedir ( id buf )
  _cluster over to DirEntry cluster ( id buf ) DirEntry SZ +
  V2 V1 :FirstSectorOfCluster 1 V1 :readsector
  V1 :dirwin :buf( dup DirEntry NAMESZ SPC fill '.' over c! _makedir ( id buf )
  V2 over to DirEntry cluster ( id buf ) DirEntry SZ +
  dup DirEntry NAMESZ SPC fill '.' over c!+ '.' swap c! ( id buf )
  _makedir ( id buf ) _parentcl swap to DirEntry cluster
  _self writecursector ( id ) ;
  _makedir ( id buf ) V3 swap to DirEntry cluster
  2rdrop r> writecursector ( id ) ;

0 value self
\ write multiple sectors from buf
: writesectors ( sec u buf self -- ) to self
  rot >r swap for ( buf ) \ V1=sec
    V1 over self :drv :sec! to1+ V1 self :drv secsz + next ( buf )
  drop rdrop ;
: writesectors ( sec u buf self -- ) >r \ V1=self
  rot >r swap for ( buf ) \ V2=sec
    V2 over V1 :drv :sec! to1+ V2 V1 :drv secsz + next ( buf )
  drop 2rdrop ;

: writecluster ( cluster src self -- ) >r
  over 2 - $fff6 > if abort" cluster out of range!" then


@@ 196,8 194,8 @@ $e5 const DIRFREE
: fatinfo ( id self -- info ) FATInfo :read ;

\ TODO: deallocate the chain before clearing the entry
: fatremove ( id self -- ) >r
  r@ :getdirentry ( dirent ) DIRFREE swap c! r> writecursector ;
: fatremove ( id self -- )
  tuck :getdirentry ( dirent ) DIRFREE swap c! writecursector ;

\ This approach to iteration is inefficient, but simple. I keep it as-is for now
: _next ( entry self -- entry-or-0 ) >r \ V1=self


@@ 211,7 209,7 @@ $e5 const DIRFREE
      V1 _next dup while dup V1 :getid V2 <> while repeat then then ( entry-or-0 )
  dup if V1 _next dup if V1 :getid then then 2rdrop ;

: _patchFS ( fs -- ) >r \ V1=fs
: :patchlo ( fs -- ) >r \ V1=fs
  ['] fatinfo r@ 12 + ! ['] fatiter r@ 20 + !
  ['] fatnewfile r@ 24 + !  ['] fatnewdir r@ 28 + ! ['] fatremove r@ 32 + !
  ['] fatwritebuf FATFile EmptyCursor 8 + !


@@ 219,9 217,7 @@ $e5 const DIRFREE
  ['] fatflush FATFile EmptyCursor 12 + !
  ['] fattruncate FATFile EmptyCursor 40 + !
  1 r> to flags ;
: :mountvolume ( drv -- fs ) FAT :mountvolume dup _patchFS ;

bootfs 12 + @ ' abort = [if] bootfs _patchFS [then]
: :mountvolume ( drv -- fs ) FAT :mountvolume dup :patchlo ;

create _FATTemplate
( jmp )  $eb c, $3c c, $90 c, ( OEMName ) ," DuskFAT " ( BytsPerSec ) 0 c, 0 c,


@@ 232,14 228,12 @@ create _FATTemplate
( BootSig ) $29 c, ( VolID ) 0 , ( VolLabel ) ," NONAME     "
( FilSysType ) ," FAT12   "

0 value fatseccnt
0 value secsz
: newFAT12 ( drv -- )
  fatopts clustercnt 341 / 1+ to fatseccnt
  ( drv ) dup Drive secsz to secsz ( drv )
  here secsz 0 fill
  fatopts clustercnt 341 / 1+ >r \ V1=fatseccnt
  ( drv ) dup Drive secsz >r ( drv ) \ V2=secsz
  here V2 0 fill
  _FATTemplate here $3e move ( drv )
  secsz here $0b + w!
  V2 here $0b + w!
  fatopts secpertrk here $18 + w!
  fatopts numheads here $1a + w!
  fatopts drvnum here $24 + c!


@@ 247,16 241,16 @@ create _FATTemplate
  fatopts rsvdsec here $0e + w!
  fatopts rootentsec DirEntry SZ * here $11 + w!
  fatopts clustercnt fatopts secperclus * fatopts rootentsec +
  fatopts rsvdsec + fatseccnt + dup here $13 + w!
  fatopts rsvdsec + V1 + dup here $13 + w!
  ." TotSec " . nl>
  fatseccnt here $16 + w!
  V1 here $16 + w!
  $aa55 here $1fe + w!
  ( drv ) dup 0 here rot Drive :sec! ( drv )
  \ header done. Now, zero-out all FAT and root dir entries
  here secsz 0 fill
  fatopts rootentsec fatseccnt + 1- fatopts rsvdsec 1+ swap for ( drv sec )
  here V2 0 fill
  fatopts rootentsec V1 + 1- fatopts rsvdsec 1+ swap for ( drv sec )
    2dup here rot Drive :sec! next ( drv sec ) drop
  \ finally, initialize the first FAT sector
  $fffff0 here !
  ( drv ) fatopts rsvdsec here rot Drive :sec! ;
  ( drv ) fatopts rsvdsec here rot Drive :sec! 2rdrop ;
]struct

M fs/fs/fatlo.fs => fs/fs/fatlo.fs +17 -18
@@ 54,15 54,16 @@ sfield bufcluster \ cluster number of current buf
sfield lastcursor
sfield fatwin \ FAT secwin
sfield dirwin \ DirEntry secwin

SZ &+ :hdr(
SZ $0b + &+w@ secsz          \ in bytes
SZ $0d + &+c@ secpercluster
SZ $0e + &+w@ reservedseccnt \ number of sectors reserved before FAT starts
SZ $10 + &+c@ FATcnt         \ >1 means backup FATs
SZ $11 + &+w@ rootentcnt     \ count of 32b entries
SZ $13 + &+w@ seccnt
SZ $16 + &+w@ FATsz          \ in sectors
\ FAT header now
$0b sallot
sfieldw secsz \ in bytes
sfieldb secpercluster
sfieldw reservedseccnt
sfieldb FATcnt
sfieldw rootentcnt
sfieldw seccnt
1 sallot
sfieldw FATsz \ in sectors
$18 const HDRSZ
: :fatwin [compile] fatwin [compile] SectorWindow ; immediate
: :dirwin [compile] dirwin [compile] SectorWindow ; immediate


@@ 77,13 78,13 @@ $18 const HDRSZ
: :ClusterSize bi secpercluster | secsz * ;
: :FAT12? :CountOfClusters 4085 < ;

: cl# ( n -- ) not if abort" cluster out of range" then ;
: :FirstSectorOfCluster ( n self -- sec ) >r
  dup << r@ secsz r@ FATsz * >= if abort" cluster out of range" then
  1- 1- r@ secpercluster * r> :FirstDataSector + ;
  dup << r@ secsz r@ FATsz * < cl#
  2 - r@ secpercluster * r> :FirstDataSector + ;

: :readsector ( sec cnt self -- ) r! :dirwin :move 0 r> :dirwin :seek 2drop ;

: cl# ( n -- ) not if abort" cluster out of range" then ;
: :FAT12@ ( cluster self -- entry ) >r
  dup dup >> + ( cl offset ) dup r@ :fatwin :seek cl# c@ ( cl off lsb )
  swap 1+ r> :fatwin :seek cl# c@ 8 lshift or ( cl entry )


@@ 121,9 122,7 @@ $18 const HDRSZ

\ Get DirEntry address from FS ID "id"
: :getdirentry ( id self -- direntry )
  over if
    r! secsz /mod ( offset sec ) 1 r@ :readsector ( off ) r> :dirwin :buf( +
  else 2drop rootdirentry( then ;
  over if dup :dirwin :fulldrv :dirwin :seek cl# else 2drop rootdirentry( then ;

\ Get ID for direntry
: :getid ( direntry self -- id )


@@ 185,7 184,7 @@ extends File struct[ FATFile
    r@ :ptr r@ :)buf over - ( n a nmax )
    rot min ( a n ) dup r> to+ pos ( a n ) ;

  : :fatclose ( self -- ) dup IO :flush :release ;
  : :fatclose ( self -- ) dup :flush :release ;

  \ these words below are "static" words not called with "self" as an argument,
  \ but "fat".


@@ 223,8 222,8 @@ struct+[ FAT
  : :mountvolume ( drv -- fs )
    dup SectorWindow :new over SectorWindow :new rot
    here >r ( fatwin dirwin rot ) \ V1=fs
    dup , 0 ( flags ) , ['] :child , ['] abort , ['] :fatopen , ['] abort ,
    ['] abort , ['] abort , ['] abort ,
    dup , 0 ( flags ) , ['] :child , ['] abort , ['] :fatopen ,
    ['] abort dup , dup , dup , ,
    0 ( bufcluster ) , 0 ( lastcursor ) , rot ( fatwin ) , swap ( dirwin ) ,
    \ At this point, "here" points to the FAT-header-to-be. Read the first sector
    \ directly in "here": we'll have the header right here!

M fs/lib/drivelo.fs => fs/lib/drivelo.fs +1 -0
@@ 15,6 15,7 @@ struct[ SectorWindow
      2dup tuck fsec - swap cnt >= if abort" secwin oor" then ( sec self )
      dup :flush 2dup to sec tuck :buf( rot :drv :sec@ else 2drop then ;
  : :move ( fsec cnt self -- ) swap 1 max over to cnt to fsec ;
  : :fulldrv ( self -- ) 0 over :drv seccnt rot :move ;
  : :seek ( pos self -- a? n-or-0 )
    r! :drv secsz /mod ( off relsec ) \ V1=self
    dup r@ cnt < if ( off relsec )

M fs/xcomp/i386/pc/init.fs => fs/xcomp/i386/pc/init.fs +1 -0
@@ 31,6 31,7 @@ f<< /drv/pc/pic.fs
pic$ idt$

f<< /fs/fat.fs
bootfs FAT :patchlo

f<< /sys/kbd.fs
f<< /sys/mouse.fs