summaryrefslogtreecommitdiffstats
path: root/main/common/fatfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'main/common/fatfs.c')
-rw-r--r--main/common/fatfs.c696
1 files changed, 696 insertions, 0 deletions
diff --git a/main/common/fatfs.c b/main/common/fatfs.c
new file mode 100644
index 0000000..34c6275
--- /dev/null
+++ b/main/common/fatfs.c
@@ -0,0 +1,696 @@
+/* vi: set ts=4: */
+/* fatfs.c:
+ * This is a front end (i.e. the CLI portion) of the dosfs.c source code.
+ * The dosfs.c file is code from Lewin Edwards. The website I got this
+ * from originally was: http://www.zws.com/products/dosfs/index.html .
+ *
+ * The dosfs.c dosfs.h files in uMon common (i.e. here) are taken directly
+ * from that website, with minimal modification (so as to remain compatible
+ * with any DOSFS updates). Much of this fatfs code is also shamelessly
+ * cut-and-pasted from Lewin's source file main.c (part of the dosfs
+ * tarball) used to demonstrate the dosfs interface.
+ *
+ * Discussion on uMon's philosophy of file-systems other than TFS...
+ * The intent under the scope of uMon for support of file systems other than
+ * TFS is to support two commands: a file-system-specific command and an
+ * interface-specific command. The goal is that members of the two different
+ * command sets can be mixed and matched as needed in a particular design.
+ * For example, if we have commands for compact flash (CF), SPI and I2C
+ * interfaces the "fatfs" command could use anyone of them to retrieve files
+ * from that interface (assuming of course, that the interface has an FAT
+ * FS on the other side).
+ *
+ * The way this works is simple, the only thing the fatfs command needs is
+ * a set of interface-specific functions: readblock and writeblock. As
+ * long as the CF/SPI/I2C commands support this, and also support the
+ * ability to share those interface functions through the CLI, it simply
+ * becomes a matter of assigning the function pointers in a startup script
+ * when uMon boots up (probably in monrc).
+ *
+ * That being said, here's the model...
+ *
+ * File-system-specific Command:
+ * Each command will support the ability to establish its read and write
+ * pointers through the command line. The -r and -w options do this in
+ * the fatfs command, and it would be nice if other similar commands could
+ * follow the same model. The command should support (at minimum) the
+ * ability to list the files in the FS (ls), query for the presence of a
+ * specific file within the FS (qry), copy a file from the FS to TFS or
+ * ram (get), and also dump the content of an ASCII file from the FS to the
+ * console (cat). If the command supports modification of the FS, then,
+ * it should also support the ability remove (rm) and copy from ram or TFS
+ * to the FS (put). The command also supports default shell variables that
+ * may contain the read write functions.
+ *
+ * Interface-specific Command:
+ * Each command will support the potential of multiple interfaces of the
+ * same type. The command must be able to initialize (with optional
+ * verbosity) said interface and populate a defined set of shell variables
+ * with the address of the read and write functions applicable to that
+ * interface. Ideally the interface command should also support the ability
+ * to do raw reads (FS to memory) and writes (memory to FS) on the interface.
+ *
+ * With the above model we then have the ability to connect the "FS" command
+ * with any "Interface" command; so as file system support in uMon grows,
+ * it immediately becomes useful on a variety of interfaces, as long as
+ * they adhere to the above simple model. As of this writing the "cf" and
+ * "fatfs" commands comply to this model and can be used as a template for
+ * developing new commands that fit into this category.
+ *
+ * Here is an example of their usage:
+ *
+ * uMON> cf init FATFS # Initialize the compact flash interface and
+ * # laod FATFS_RD and FATFS_WR with the read and
+ * # write function pointers.
+ * uMON> fatfs cat file1 # Using the FATFS_RD and FATFS_WR shell variables
+ * # previously set up, dump the content of the file
+ * # named 'file1'.
+ *
+ * General notice:
+ * This code is part of a boot-monitor package developed as a generic base
+ * platform for embedded system designs. As such, it is likely to be
+ * distributed to various projects beyond the control of the original
+ * author. Please notify the author of any enhancements made or bugs found
+ * so that all may benefit from the changes. In addition, notification back
+ * to the author will allow the new user to pick up changes that may have
+ * been made by other users after this version of the code was distributed.
+ *
+ * Note1: the majority of this code was edited with 4-space tabs.
+ * Note2: as more and more contributions are accepted, the term "author"
+ * is becoming a mis-representation of credit.
+ *
+ * Original author: Ed Sutter esutter@lucent.com
+ * Contributor(s): Graham Henderson
+ */
+
+#include "config.h"
+#if INCLUDE_FATFS
+#include "stddefs.h"
+#include "genlib.h"
+#include "cli.h"
+#include "tfs.h"
+#include "tfsprivate.h"
+#include "dosfs.h"
+
+static int (*fatfsRead)(int interface, char *buf, int blknum, int count);
+static int (*fatfsWrite)(int interface, char *buf, int blknum, int count);
+
+static char fatfs_initialized;
+static char *fatfs_tmp_space;
+static VOLINFO vi __attribute__((aligned (32)));
+static uint8_t sector[SECTOR_SIZE] __attribute__ ((aligned (32)));
+static uint8_t sector2[SECTOR_SIZE] __attribute__ ((aligned (32)));
+
+/* Support skipping LFN dir entries...
+ */
+#define ATTR_LONG_NAME \
+ (ATTR_READ_ONLY | ATTR_HIDDEN | ATTR_SYSTEM | ATTR_VOLUME_ID)
+
+#define FATFS_FNAME_STR "FATFSFNAME"
+#define FATFS_FTOT_STR "FATFSFTOT"
+#define FATFS_FSIZE_STR "FATFSFSIZE"
+
+/* fatfsInit():
+ * Start up the fs by reading in volume information.
+ * This function will return if already initialized, unless force
+ * is nonzero.
+ */
+static int
+fatfsInit(int force, int verbose)
+{
+ uint8_t pactive, ptype;
+ uint32_t pstart, psize;
+
+ if ((fatfs_initialized == 1) && (force == 0))
+ return(0);
+
+ /* Obtain pointer to first partition on first (only) unit.
+ */
+ pstart = DFS_GetPtnStart(0, sector, 0, &pactive, &ptype, &psize);
+ if (pstart == 0xffffffff) {
+ printf("Cannot find first partition\n");
+ return(-1);
+ }
+
+ if (verbose) {
+ printf("Partition 0...\n");
+ printf(" Start sector 0x%08lx\n",pstart);
+ printf(" Active %d\n",pactive);
+ printf(" Type 0x%x\n",ptype);
+ printf(" Size 0x%lx\n",psize);
+ }
+
+ if (DFS_GetVolInfo(0, sector, pstart, &vi)) {
+ printf("Error getting volume information\n");
+ return(-1);
+ }
+
+ if (verbose) {
+ printf("Volume label '%-11s'\n", vi.label);
+ printf(" %d sector(s) per cluster\n",vi.secperclus);
+ printf(" %d reserved sector(s)\n",vi.reservedsecs);
+ printf(" %d total volume sector(s)\n", vi.numsecs);
+ printf(" %d sectors per FAT\n",vi.secperfat);
+ printf(" first FAT at sector #%d\n",vi.fat1);
+ printf(" root dir at #%d\n",vi.rootdir);
+
+ printf("For.. FAT32 rootdir is CLUSTER #,\n");
+ printf(" FAT12/16 rootdir is a SECTOR #.\n");
+ printf("%d root dir entries, data area commences at sector #%d.\n",
+ vi.rootentries,vi.dataarea);
+ printf("%d clusters (%d bytes) in data area, filesystem IDd as ",
+ vi.numclusters, vi.numclusters * vi.secperclus * SECTOR_SIZE);
+
+ if (vi.filesystem == FAT12)
+ printf("FAT12.\n");
+ else if (vi.filesystem == FAT16)
+ printf("FAT16.\n");
+ else if (vi.filesystem == FAT32)
+ printf("FAT32.\n");
+ else
+ printf("[unknown]\n");
+ }
+ fatfs_initialized = 1;
+ return(0);
+}
+
+/* fatfsCat():
+ * Dump the content of the specified fatfs file to the console.
+ * This function assumes the data is ASCII.
+ */
+static int
+fatfsCat(char *filepath)
+{
+ uint32_t i, j;
+ FILEINFO fi;
+ uint8_t *p;
+
+ if (DFS_OpenFile(&vi, (uint8_t *)filepath, DFS_READ, sector, &fi)) {
+ printf("error opening '%s'\n",filepath);
+ return(-1);
+ }
+ p = (uint8_t *)fatfs_tmp_space;
+ DFS_ReadFile(&fi, sector, p, &i, fi.filelen);
+ for(j=0;j<fi.filelen;j++)
+ putchar(*p++);
+ putchar('\n');
+ return(0);
+}
+
+/* fatfsGet():
+ * Retreive a file from the FATFS and place it in the specified destination.
+ * The destination may be either a TFS filename or a hex address
+ * (indicated by a leading "0x").
+ *
+ * Input:
+ * char *fatfspath
+ * Pointer to FATFS file and path.
+ * char *dest
+ * Pointer to TFS filename or a addr,len string.
+ * The expected "addr,len" syntax is 0xADDR,LEN or 0xADDR,0xLEN.
+ */
+static int
+fatfsGet(char *fatfile, char *dest)
+{
+ FILEINFO fi;
+ char *p, tfs;
+ uint32_t i;
+
+ if (DFS_OpenFile(&vi, (uint8_t *)fatfile, DFS_READ, sector, &fi)) {
+ printf("error opening file\n");
+ return(-1);
+ }
+ if (strncmp(dest,"0x",2) == 0) {
+ tfs = 0;
+ p = (char *)strtoul(dest,0,0);
+ }
+ else {
+ tfs = 1;
+ p = fatfs_tmp_space;
+ }
+
+ DFS_ReadFile(&fi, sector, (uint8_t *)p, &i, fi.filelen);
+ if (i != fi.filelen) {
+ printf("read %d, expected %d\n",i,fi.filelen);
+ return(-1);
+ }
+ if (tfs) {
+#if INCLUDE_TFS
+ int tfserr;
+ char *flags, *info;
+
+ flags = info = (char *)0;
+ if ((flags = strchr(dest,','))) {
+ *flags++ = 0;
+ if ((info = strchr(flags,',')))
+ *info++ = 0;
+ }
+ tfserr = tfsadd(dest,info,flags,(uchar *)p,fi.filelen);
+ if (tfserr != TFS_OKAY) {
+ printf("TFS error: %s\n",tfserrmsg(tfserr));
+ return(-1);
+ }
+#else
+ printf("TFS not built in\n");
+ return(-1);
+#endif
+ }
+ return(0);
+}
+
+/* fatfsPut():
+ * Copy data or file to a FATFS file.
+ *
+ * Input:
+ * char *fatfspath
+ * Pointer to FATFS file and path.
+ * char *src
+ * Pointer to TFS filename or a addr,len string.
+ * The expected "addr,len" syntax is 0xADDR,LEN or 0xADDR,0xLEN.
+ */
+static int
+fatfsPut(char *src, char *fatfspath)
+{
+ FILEINFO fi;
+ char tfs, *p, *cp;
+ uint32_t successcount, len, size, rc;
+
+ if (strncmp(src,"0x",2) == 0) {
+ tfs = 0;
+ p = (char *)strtoul(src,&cp,0);
+ cp++;
+ len = strtoul(cp,0,0);
+ }
+ else {
+#if INCLUDE_TFS
+ TFILE *tfp;
+
+ tfs = 1;
+ if ((tfp = tfsstat(src)) == 0) {
+ printf("Can't find file '%s' in TFS\n",src);
+ return(CMD_FAILURE);
+ }
+ p = TFS_BASE(tfp);
+ len = TFS_SIZE(tfp);
+#else
+ printf("TFS not built in\n");
+ return(-1);
+#endif
+ }
+
+ /* Copy 'len' bytes from 'p' to DOSFS file 'fatfspath'...
+ */
+ if (DFS_OpenFile(&vi, (uint8_t *)fatfspath, DFS_WRITE, sector, &fi)) {
+ printf("error opening '%s'\n",fatfspath);
+ return(-1);
+ }
+
+ while(len > 0) {
+ if (len >= SECTOR_SIZE)
+ size = SECTOR_SIZE;
+ else
+ size = len;
+
+ rc = DFS_WriteFile(&fi, sector2, (uint8_t *)p, &successcount, size);
+ if ((rc != DFS_OK) || (successcount != size)) {
+ printf("error writing '%s'\n",fatfspath);
+ return(-1);
+ }
+ p += size;
+ len -= size;
+ }
+ return(0);
+}
+
+/* fatfsRm():
+ * Remove the specified file from the FATFS.
+ * If the path is a directory, then don't remove anything.
+ */
+static int
+fatfsRm(char *fatfspath)
+{
+ DIRINFO di;
+
+ di.scratch = sector;
+ if (DFS_OpenDir(&vi, (uint8_t *)fatfspath, &di) == 0) {
+ printf("can't remove directory '%s'\n",fatfspath);
+ return(-1);
+ }
+ if (DFS_UnlinkFile(&vi, (uint8_t *)fatfspath, sector)) {
+ printf("error unlinking file %s\n",fatfspath);
+ return(-1);
+ }
+ return(0);
+}
+
+/* fatfsLs():
+ * The incoming string is assumed to be some directory name.
+ * If NULL, then it is assumed to be the CF's top-most level.
+ */
+static int
+fatfsLs(char *dirname)
+{
+ int ftot;
+ DIRENT de;
+ DIRINFO di;
+ char *dir;
+
+ if (dirname)
+ dir = dirname;
+ else
+ dir = "";
+
+ di.scratch = sector;
+ if (DFS_OpenDir(&vi, (uint8_t *)dir, &di)) {
+ printf("Can't open dir: <%s>\n",dirname);
+ return(CMD_FAILURE);
+ }
+
+ ftot = 0;
+ while (!DFS_GetNext(&vi, &di, &de)) {
+ char tmp[32];
+
+ if (de.name[0] && ((de.attr & ATTR_LONG_NAME) != ATTR_LONG_NAME)) {
+ if ((de.attr & ATTR_VOLUME_ID) > 0) {
+ de.name[8] = 0;
+ printf("Volume: %s\n",de.name);
+ continue;
+ }
+ ftot++;
+
+ printf("%02d/%02d/%4d %02d:%02d ",
+ CREATE_MON(de), CREATE_DAY(de), CREATE_YEAR(de),
+ CREATE_HR(de), CREATE_MIN(de));
+
+ if ((de.attr & ATTR_DIRECTORY) > 0) {
+ // truncate the extension
+ de.name[8] = 0;
+
+ printf("<DIR> %-8s",de.name);
+ }
+ else {
+ DFS_DirToCanonical((uint8_t *)tmp,de.name);
+ printf(" %8d %-12s",FILESIZE(de), tmp);
+ }
+
+ printf(" %c%c%c%c%c\n",
+ (( de.attr & ATTR_VOLUME_ID) ? 'V' : ' '),
+ (( de.attr & ATTR_READ_ONLY) ? 'R' : ' '),
+ (( de.attr & ATTR_ARCHIVE ) ? 'A' : ' '),
+ (( de.attr & ATTR_SYSTEM ) ? 'S' : ' '),
+ (( de.attr & ATTR_HIDDEN ) ? 'H' : ' '));
+ }
+ }
+ shell_sprintf(FATFS_FTOT_STR,"%d",ftot);
+ return(0);
+}
+
+static int
+fatfsQry(char *fatfspath, int verbose)
+{
+ DIRENT de;
+ DIRINFO di;
+ char *lastslash, *fname, *dir, pathcopy[80], matchname[80];
+ int flen, flen1, fsize, pathlen, match, ftot;
+
+ if (!fatfspath)
+ return(-1);
+
+ /* Prior to each 'ls', clear the content of the name and
+ * size shell variables...
+ */
+ setenv(FATFS_FNAME_STR,0);
+ setenv(FATFS_FSIZE_STR,0);
+ setenv(FATFS_FTOT_STR,0);
+
+ pathlen = strlen(fatfspath);
+ if (pathlen > sizeof(pathcopy)) {
+ printf("path too big\n");
+ return(-1);
+ }
+ strcpy(pathcopy, fatfspath);
+ lastslash = strrchr(pathcopy,DIR_SEPARATOR);
+
+ if (lastslash == 0) {
+ dir = "";
+ fname = pathcopy;
+ }
+ else {
+ *lastslash = 0;
+ dir = pathcopy;
+ fname = lastslash+1;
+ }
+
+ flen = strlen(fname);
+ if (verbose > 1)
+ printf("Qry opening dir <%s>, fname <%s>...\n",dir,fname);
+
+ di.scratch = sector;
+ if (DFS_OpenDir(&vi, (uint8_t *)dir, &di)) {
+ printf("error opening subdirectory\n");
+ return(CMD_FAILURE);
+ }
+
+ match = fsize = ftot = flen1 = 0;
+ while (!DFS_GetNext(&vi, &di, &de)) {
+ int i;
+ char dosname[16];
+
+ memset(dosname,0,sizeof(dosname));
+ if (de.name[0] && ((de.attr & ATTR_LONG_NAME) != ATTR_LONG_NAME)) {
+ if ((de.attr & ATTR_VOLUME_ID) || (de.attr & ATTR_DIRECTORY)) {
+ for(i=0;i<8;i++) {
+ if (de.name[i] != ' ') {
+ dosname[i] = de.name[i];
+ }
+ else {
+ dosname[i] = 0;
+ break;
+ }
+ }
+ dosname[8] = 0;
+ }
+ else
+ DFS_DirToCanonical((uint8_t *)dosname,de.name);
+
+ flen1 = strlen(dosname);
+
+ if ((fname[0] == '*') && (fname[flen-1] == '*')) {
+ fname[flen-1] = 0;
+ if (strstr(dosname,fname+1))
+ match = 1;
+ fname[flen-1] = '*';
+ }
+ else if (fname[0] == '*') {
+ if (!strcmp(dosname+(flen1-flen+1),fname+1))
+ match = 1;
+ }
+ else if (fname[flen-1] == '*') {
+ fname[flen-1] = 0;
+ if (!strncmp(dosname,fname,flen-1))
+ match = 1;
+ fname[flen-1] = '*';
+ }
+ else if (!strcmp(dosname,fname)) {
+ match = 1;
+ }
+ if (match) {
+ strcpy(matchname,dosname);
+ fsize = FILESIZE(de);
+ ftot++;
+ match = 0;
+ if (verbose)
+ printf(" %s (%d)\n",dosname,fsize);
+ }
+ }
+ }
+ shell_sprintf(FATFS_FTOT_STR,"%d",ftot);
+ if (ftot) {
+ shell_sprintf(FATFS_FSIZE_STR,"%d",fsize);
+ setenv(FATFS_FNAME_STR,matchname);
+ }
+ return(0);
+}
+
+
+char *FatfsHelp[] = {
+ "Fat 12|16|32 File System Support",
+ "[r:s:w:v] {operation} [args]...",
+#if INCLUDE_VERBOSEHELP
+ "",
+ "Options:",
+ " -r {addr} set read-block func ptr (default: FATFS_RD)",
+ " -s {addr} base of ram scratch space used by fatfs",
+ " (default is APPRAMBASE)",
+ " -w {addr} set write-block func ptr (default: FATFS_WR)",
+ " -v additive verbosity",
+ "",
+ "Operations:",
+ " cat {fname}",
+ " get {fat_file} {tfs_file | addr}",
+ " (get from fatfs)",
+ " init initialize internal structures",
+ " put {tfs_file | addr,size} {fat_file}",
+ " (put to fatfs)",
+ " ls [dir] list files within specified directory (or top)",
+ " qry {fltr} qry for file or directory presence",
+ " - fltr format: sss, *sss, sss*, *sss* ('sss' is any string)",
+ " - loads " FATFS_FNAME_STR " & " FATFS_FSIZE_STR " based on most recent match",
+ " - loads " FATFS_FTOT_STR " with number of files listed",
+ " rm {fname}",
+#endif
+ 0
+};
+
+/* FatfsCmd():
+ * This command provides a front end (command line interface) to the
+ * dosfs.c code. The intent is that this be a template for other
+ * "fs-ish" commands within uMon (refer to discussion at the top of this
+ * file).
+ */
+int
+FatfsCmd(int argc, char *argv[])
+{
+ uint32_t i, j;
+ int opt, verbose;
+ char *cmd, *env, *arg1, *arg2, *arg3;
+
+ /* Establish default read/write functions to access underlying
+ * storage media. These defaults can be overridden by the
+ * command line options -r & -w below.
+ */
+ if ((env = getenv("FATFS_RD")) != 0)
+ fatfsRead = (int(*)(int,char*,int,int))strtol(env,0,0);
+
+ if ((env = getenv("FATFS_WR")) != 0)
+ fatfsWrite = (int(*)(int,char*,int,int))strtol(env,0,0);
+
+ verbose = 0;
+ fatfs_tmp_space = (char *)0xffffffff;
+ while ((opt=getopt(argc,argv,"r:s:vw:")) != -1) {
+ switch(opt) {
+ case 'r':
+ fatfsRead = (int(*)(int,char*,int,int))strtoul(optarg,0,0);
+ break;
+ case 's':
+ fatfs_tmp_space = (char *)strtoul(optarg,0,0);
+ break;
+ case 'w':
+ fatfsWrite = (int(*)(int,char*,int,int))strtoul(optarg,0,0);
+ break;
+ case 'v':
+ verbose++;
+ break;
+ default:
+ return(CMD_PARAM_ERROR);
+ }
+ }
+
+ if ((fatfsRead == 0) || (fatfsWrite == 0)) {
+ printf("FATFS access pointers not initialized\n");
+ return(CMD_FAILURE);
+ }
+
+ if (argc < optind + 1)
+ return(CMD_PARAM_ERROR);
+
+ if (fatfs_tmp_space == (char *)0xffffffff)
+ fatfs_tmp_space = (char *)getAppRamStart();
+
+ cmd = argv[optind];
+ arg1 = argv[optind+1];
+ arg2 = argv[optind+2];
+ arg3 = argv[optind+3];
+
+ if (strcmp(cmd,"init") == 0) {
+ if (fatfsInit(1,verbose) < 0)
+ return(CMD_FAILURE);
+ }
+ else if (strcmp(cmd,"cat") == 0) {
+ if (argc != optind + 2)
+ return(CMD_PARAM_ERROR);
+
+ if (fatfsInit(0,0) < 0)
+ return(CMD_FAILURE);
+
+ for(i=optind+1;i<argc;i++) {
+ if (fatfsCat(argv[i]) < 0)
+ return(CMD_FAILURE);
+ }
+ }
+ else if (strcmp(cmd,"get") == 0) {
+ if (argc != optind + 3)
+ return(CMD_PARAM_ERROR);
+
+ if (fatfsInit(0,0) < 0)
+ return(CMD_FAILURE);
+
+ if (fatfsGet(arg1,arg2) < 0)
+ return(CMD_FAILURE);
+
+ }
+ else if (strcmp(cmd,"put") == 0) {
+ if (argc != optind + 3)
+ return(CMD_PARAM_ERROR);
+
+ if (fatfsInit(0,0) < 0)
+ return(CMD_FAILURE);
+
+ if (fatfsPut(arg1,arg2) < 0)
+ return(CMD_FAILURE);
+ }
+ else if (strcmp(cmd,"qry") == 0) {
+ if (argc != optind + 2)
+ return(CMD_PARAM_ERROR);
+
+ if (fatfsInit(0,0) < 0)
+ return(CMD_FAILURE);
+
+ if (fatfsQry(arg1,verbose) < 0)
+ return(CMD_FAILURE);
+ }
+ else if (strcmp(cmd,"ls") == 0) {
+ if (fatfsInit(0,0) < 0)
+ return(CMD_FAILURE);
+
+ if (fatfsLs(arg1) < 0)
+ return(CMD_FAILURE);
+ }
+ else if (strcmp(cmd,"rm") == 0) {
+ if (fatfsInit(0,0) < 0)
+ return(CMD_FAILURE);
+
+ for(j=optind+1;j<argc;j++) {
+ if (fatfsRm(argv[j]) < 0)
+ return(CMD_FAILURE);
+ }
+ }
+ else {
+ printf("fatfs op <%s> not found\n",cmd);
+ return(CMD_FAILURE);
+ }
+
+ return(CMD_SUCCESS);
+}
+
+/* Hookup between DOSFS and this command...
+ * The dosfs.c code requires that the user provide two functions
+ * (DFS_ReadSector() and DFS_WriteSector()) to hook it up to an
+ * external interface. These two functions are configured by
+ * the fatfs command to point to whatever driver is to be established
+ * as the FATFS physical interface. For more information refer to the
+ * discussion at the top of this file.
+ */
+uint32_t
+DFS_ReadSector(uint8_t unit, uint8_t *data, uint32_t sec,uint32_t count)
+{
+ return((uint32_t)fatfsRead((int)unit, (char *)data, sec, count));
+}
+
+uint32_t
+DFS_WriteSector(uint8_t unit, uint8_t *data, uint32_t sec,uint32_t count)
+{
+ return((uint32_t)fatfsWrite((int)unit, (char *)data, sec, count));
+}
+
+#endif