~vdupras/duskos

a92b09de2de58cef88683872cd19725f270d9213 — Virgil Dupras 23 days ago 477ee1d
fs/fat2: first step

This is the first step in porting ChaN's FATFS implementation.

This won't replace fs/fatlo, which needs to be in Forth to serve as a boot FS,
but it will replace fs/fat, which is hastly written and not super solid.
M Makefile => Makefile +3 -7
@@ 61,13 61,9 @@ testlib: dusk
testcc: dusk
	echo "' byefail ' abort realias f<< tests/comp/c/all.fs bye" | ./dusk || (echo; exit 1)

.PHONY: testhal
testhal: dusk
	echo "' byefail ' abort realias f<< tests/asm/hal.fs bye" | ./dusk || (echo; exit 1)

.PHONY: testtext
testuxn: dusk
	echo "' byefail ' abort realias f<< tests/emul/uxn/all.fs bye" | ./dusk || (echo; exit 1)
.PHONY: testfat
testfat: dusk
	echo "' byefail ' abort realias f<< tests/fs/fat.fs bye" | ./dusk || (echo; exit 1)

.PHONY: clean
clean:

M fs/comp/c/lib.fs => fs/comp/c/lib.fs +12 -3
@@ 125,14 125,23 @@ calias 0-9? int isdigit(char c);
  0 _sfile MemFile :seek _sfile fscanf ;
:c int sscanf(char* fmt, char *str);

:c struct Drive {
    uint secsz;
    uint seccnt;
    void *_secfetch;
    void *_secstore;
};

:c struct File {
    unsigned int putback;
    uint putback;
    void *_readbuf;
    void *_writebuf;
    void *_flush;
    void *_close;
    unsigned int pos;
    unsigned int size;
    uint pos;
    uint size;
    uchar *bufptr;
    uint bufsz;
    void *_seek;
};


A fs/fs/fat2.c => fs/fs/fat2.c +55 -0
@@ 0,0 1,55 @@
/* Source: http://elm-chan.org/fsw/ff/00index_e.html
 * License: /license/chan-fatfs.txt
 */
/* Differences with upstream
1. pdrv is a pointer to a Drive struct rather than a simple index.
2. Errors translate to aborts.
*/
typedef unsigned int	UINT;	/* int must be 16-bit or 32-bit */
typedef unsigned char	BYTE;	/* char must be 8-bit */
typedef unsigned short	WORD;	/* 16-bit unsigned integer */
typedef unsigned int	DWORD;	/* 32-bit unsigned integer */

/* Type of file size and LBA variables */
typedef DWORD FSIZE_t;
typedef DWORD LBA_t;

#define FF_MAX_SS $1000
#define RES_OK 0

struct FATFS {
	BYTE	fs_type;		/* Filesystem type (0:not mounted) */
	Drive	*pdrv;			/* Volume hosting physical drive */
	BYTE	ldrv;			/* Logical drive number (used only when FF_FS_REENTRANT) */
	BYTE	n_fats;			/* Number of FATs (1 or 2) */
	BYTE	wflag;			/* win[] status (b0:dirty) */
	BYTE	fsi_flag;		/* FSINFO status (b7:disabled, b0:dirty) */
	WORD	id;				/* Volume mount ID */
	WORD	n_rootdir;		/* Number of root directory entries (FAT12/16) */
	WORD	csize;			/* Cluster size [sectors] */
	DWORD	last_clst;		/* Last allocated cluster */
	DWORD	free_clst;		/* Number of free clusters */
	DWORD	cdir;			/* Current directory start cluster (0:root) */
	DWORD	n_fatent;		/* Number of FAT entries (number of clusters + 2) */
	DWORD	fsize;			/* Number of sectors per FAT */
	LBA_t	volbase;		/* Volume base sector */
	LBA_t	fatbase;		/* FAT base sector */
	LBA_t	dirbase;		/* Root directory base sector (FAT12/16) or cluster (FAT32/exFAT) */
	LBA_t	database;		/* Data base sector */
	LBA_t	winsect;		/* Current sector appearing in the win[] */
	BYTE	win[FF_MAX_SS];	/* Disk access window for Directory, FAT (and file data at tiny cfg) */
};

void sync_window(FATFS* fs) {
	if (fs->wflag) {	/* Is the disk access window dirty? */
		/* Write it back into the volume */
		disk_write(fs->pdrv, fs->win, fs->winsect, 1);
		fs->wflag = 0;	/* Clear window dirty flag */
		if (fs->winsect - fs->fatbase < fs->fsize) {	/* Is it in the 1st FAT? */
			if (fs->n_fats == 2) {
				/* Reflect it to 2nd FAT if needed */
				disk_write(fs->pdrv, fs->win, fs->winsect + fs->fsize, 1);
			}
		}
	}
}

A fs/fs/fat2.fs => fs/fs/fat2.fs +10 -0
@@ 0,0 1,10 @@
?f<< /comp/c/lib.fs
?f<< /lib/endian.h

: disk_write ( drv buff sector count -- )
  over + for2 ( drv buff )
    2dup swap i rot> Drive :sec! ( drv buff ) over Drive secsz + next 2drop ;
:c void disk_write(uint pdrv, uchar *buff, uint sector, uint count);
cc<< /fs/fat2.c

S" FATFS" findTypedef CDecl :export

A fs/lib/endian.h => fs/lib/endian.h +10 -0
@@ 0,0 1,10 @@
?f<< /lib/endian.fs

16b calias le@ ushort le_fetch16(uint addr);
calias le@ uint le_fetch32(uint addr);
16b calias le! void le_store16(ushort val, uint addr);
calias le! void le_store32(uint val, uint addr);
16b calias be@ ushort be_fetch16(uint addr);
calias be@ uint be_fetch32(uint addr);
16b calias be! void be_store16(ushort val, uint addr);
calias be! void be_store32(uint val, uint addr);

M fs/tests/all.fs => fs/tests/all.fs +1 -1
@@ 2,9 2,9 @@
f<< /tests/kernel.fs
f<< /tests/lib/all.fs
f<< /tests/sys/all.fs
f<< /tests/fs/all.fs
f<< /tests/comp/c/all.fs
f<< /tests/asm/all.fs
f<< /tests/fs/all.fs
f<< /tests/ar/all.fs
f<< /tests/emul/all.fs
f<< /tests/gr/all.fs

M fs/tests/fs/all.fs => fs/tests/fs/all.fs +1 -0
@@ 1,1 1,2 @@
f<< /tests/fs/dummy.fs
f<< /tests/fs/fat.fs

A fs/tests/fs/fat.fs => fs/tests/fs/fat.fs +16 -0
@@ 0,0 1,16 @@
?f<< /tests/harness.fs
?f<< /drv/ramdrive.fs
?f<< /fs/fat2.fs
testbegin
\ tests for FAT FS
$200 4 RAMDrive :new structbind RAMDrive ramdrv
here FATFS SZ allot structbind FATFS fatfs
ramdrv :self to fatfs pdrv
$deadbeef fatfs win !
0 to fatfs fatbase
1234 to fatfs fsize
0 to fatfs winsect
1 to fatfs wflag
fatfs :self sync_window
ramdrv :buf( @ $deadbeef #eq
testend

A license/chan-fatfs.txt => license/chan-fatfs.txt +24 -0
@@ 0,0 1,24 @@
FatFs License

FatFs has being developped as a personal project of the author, ChaN. It is free from the code anyone else wrote at current release. Following code block shows a copy of the FatFs license document that heading the source files.

/*----------------------------------------------------------------------------/
/  FatFs - Generic FAT Filesystem Module  Rx.xx                               /
/-----------------------------------------------------------------------------/
/
/ Copyright (C) 20xx, ChaN, all right reserved.
/
/ FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided
/ that the following condition is met:
/
/ 1. Redistributions of source code must retain the above copyright notice,
/    this condition and the following disclaimer.
/
/ This software is provided by the copyright holder and contributors "AS IS"
/ and any warranties related to this software are DISCLAIMED.
/ The copyright owner or contributors be NOT LIABLE for any damages caused
/ by use of this software.
/----------------------------------------------------------------------------*/

Therefore FatFs license is one of the BSD-style licenses, but there is a significant feature. FatFs is mainly intended for embedded systems. In order to extend the usability for commercial products, the redistributions of FatFs in binary form, such as embedded code, binary library and any forms without source code, do not need to include about FatFs in the documentations. This is equivalent to the 1-clause BSD license. Of course FatFs is compatible with the most of open source software licenses include GNU GPL. When you redistribute the FatFs source code with changes or create a fork, the license can also be changed to GNU GPL, BSD-style license or any open source software license that not conflict with FatFs license.