From c4aeb6d5abc2a42f69388e33394a6f43740486ef Mon Sep 17 00:00:00 2001 From: Dean Camera Date: Sat, 1 Sep 2012 22:55:15 +0000 Subject: Update FatFS library copies to the latest R0.09a version. --- Projects/TempDataLogger/Lib/FATFs/00readme.txt | 14 +- Projects/TempDataLogger/Lib/FATFs/diskio.c | 4 +- Projects/TempDataLogger/Lib/FATFs/diskio.h | 30 +- Projects/TempDataLogger/Lib/FATFs/ff.c | 748 ++++++++++++++---------- Projects/TempDataLogger/Lib/FATFs/ff.h | 71 +-- Projects/TempDataLogger/Lib/FATFs/ffconf.h | 17 +- Projects/Webserver/Lib/FATFs/00readme.txt | 14 +- Projects/Webserver/Lib/FATFs/diskio.c | 4 +- Projects/Webserver/Lib/FATFs/diskio.h | 14 +- Projects/Webserver/Lib/FATFs/ff.c | 750 +++++++++++++++---------- Projects/Webserver/Lib/FATFs/ff.h | 65 +-- Projects/Webserver/Lib/FATFs/ffconf.h | 14 +- 12 files changed, 1035 insertions(+), 710 deletions(-) (limited to 'Projects') diff --git a/Projects/TempDataLogger/Lib/FATFs/00readme.txt b/Projects/TempDataLogger/Lib/FATFs/00readme.txt index c78da3186..80d8843d1 100644 --- a/Projects/TempDataLogger/Lib/FATFs/00readme.txt +++ b/Projects/TempDataLogger/Lib/FATFs/00readme.txt @@ -1,4 +1,4 @@ -FatFs Module Source Files R0.08b (C)ChaN, 2011 +FatFs Module Source Files R0.09a (C)ChaN, 2012 FILES @@ -7,7 +7,8 @@ FILES ff.h Common include file for FatFs and application module. ff.c FatFs module. diskio.h Common include file for FatFs and disk I/O module. - integer.h Alternative type definitions for integer variables. + diskio.c An example of glue function to attach existing disk I/O module to FatFs. + integer.h Integer type definitions for FatFs. option Optional external functions. Low level disk I/O module is not included in this archive because the FatFs @@ -23,7 +24,7 @@ AGREEMENTS small embedded systems. This is a free software and is opened for education, research and commercial developments under license policy of following trems. - Copyright (C) 2011, ChaN, all right reserved. + Copyright (C) 2012, ChaN, all right reserved. * The FatFs module is a free software and there is NO WARRANTY. * No restriction on use. You can use, modify and redistribute it for @@ -125,3 +126,10 @@ REVISION HISTORY f_lseek() reports required table size on creating CLMP. Extended format syntax of f_printf function. Ignores duplicated directory separators in given path names. + + Sep 06,'11 R0.09 f_mkfs() supports multiple partition to finish the multiple partition feature. + Added f_fdisk(). (_MULTI_PARTITION = 2) + + Aug 27,'12 R0.09a Fixed assertion failure due to OS/2 EA on FAT12/16. + Changed API rejects null object pointer to avoid crash. + Changed option name _FS_SHARE to _FS_LOCK. diff --git a/Projects/TempDataLogger/Lib/FATFs/diskio.c b/Projects/TempDataLogger/Lib/FATFs/diskio.c index 400687734..085d5aec6 100644 --- a/Projects/TempDataLogger/Lib/FATFs/diskio.c +++ b/Projects/TempDataLogger/Lib/FATFs/diskio.c @@ -38,7 +38,7 @@ DRESULT disk_read ( BYTE drv, /* Physical drive number (0..) */ BYTE *buff, /* Data buffer to store read data */ DWORD sector, /* Sector address (LBA) */ - BYTE count /* Number of sectors to read (1..255) */ + BYTE count /* Number of sectors to read (1..128) */ ) { DataflashManager_ReadBlocks_RAM(sector, count, buff); @@ -55,7 +55,7 @@ DRESULT disk_write ( BYTE drv, /* Physical drive number (0..) */ const BYTE *buff, /* Data to be written */ DWORD sector, /* Sector address (LBA) */ - BYTE count /* Number of sectors to write (1..255) */ + BYTE count /* Number of sectors to write (1..128) */ ) { DataflashManager_WriteBlocks_RAM(sector, count, buff); diff --git a/Projects/TempDataLogger/Lib/FATFs/diskio.h b/Projects/TempDataLogger/Lib/FATFs/diskio.h index 61d6601de..d3c3149a5 100644 --- a/Projects/TempDataLogger/Lib/FATFs/diskio.h +++ b/Projects/TempDataLogger/Lib/FATFs/diskio.h @@ -2,10 +2,12 @@ / Low level disk interface module include file /-----------------------------------------------------------------------*/ -#ifndef _DISKIO +#ifndef _DISKIO_DEFINED +#define _DISKIO_DEFINED -#define _READONLY 0 /* 1: Read-only mode */ -#define _USE_IOCTL 1 +#ifdef __cplusplus +extern "C" { +#endif #include "integer.h" @@ -45,23 +47,9 @@ DRESULT disk_ioctl (BYTE, BYTE, void*); /* Generic command */ #define CTRL_SYNC 0 /* Mandatory for write functions */ -#define GET_SECTOR_COUNT 1 /* Mandatory for only f_mkfs() */ -#define GET_SECTOR_SIZE 2 /* Mandatory for multiple sector size cfg */ -#define GET_BLOCK_SIZE 3 /* Mandatory for only f_mkfs() */ -#define CTRL_POWER 4 -#define CTRL_LOCK 5 -#define CTRL_EJECT 6 -/* MMC/SDC command */ -#define MMC_GET_TYPE 10 -#define MMC_GET_CSD 11 -#define MMC_GET_CID 12 -#define MMC_GET_OCR 13 -#define MMC_GET_SDSTAT 14 -/* ATA/CF command */ -#define ATA_GET_REV 20 -#define ATA_GET_MODEL 21 -#define ATA_GET_SN 22 - -#define _DISKIO + +#ifdef __cplusplus +} #endif +#endif diff --git a/Projects/TempDataLogger/Lib/FATFs/ff.c b/Projects/TempDataLogger/Lib/FATFs/ff.c index 2e3d7a732..059b5885a 100644 --- a/Projects/TempDataLogger/Lib/FATFs/ff.c +++ b/Projects/TempDataLogger/Lib/FATFs/ff.c @@ -1,11 +1,11 @@ /*----------------------------------------------------------------------------/ -/ FatFs - FAT file system module R0.08b (C)ChaN, 2011 +/ FatFs - FAT file system module R0.09a (C)ChaN, 2012 /-----------------------------------------------------------------------------/ / FatFs module is a generic FAT file system module for small embedded systems. / This is a free software that opened for education, research and commercial / developments under license policy of following terms. / -/ Copyright (C) 2011, ChaN, all right reserved. +/ Copyright (C) 2012, ChaN, all right reserved. / / * The FatFs module is a free software and there is NO WARRANTY. / * No restriction on use. You can use, modify and redistribute it for @@ -86,7 +86,13 @@ / Jan 15,'11 R0.08b Fast seek feature is also applied to f_read() and f_write(). / f_lseek() reports required table size on creating CLMP. / Extended format syntax of f_printf function. -/ Ignores duplicated directory separators in given path names. +/ Ignores duplicated directory separators in given path name. +/ +/ Sep 06,'11 R0.09 f_mkfs() supports multiple partition to finish the multiple partition feature. +/ Added f_fdisk(). (_MULTI_PARTITION = 2) +/ Aug 27,'12 R0.09a Fixed assertion failure due to OS/2 EA on FAT12/16 volume. +/ Changed f_open() and f_opendir reject null object pointer to avoid crash. +/ Changed option name _FS_SHARE to _FS_LOCK. /---------------------------------------------------------------------------*/ #include "ff.h" /* FatFs configurations and declarations */ @@ -99,7 +105,7 @@ ---------------------------------------------------------------------------*/ -#if _FATFS != 8237 +#if _FATFS != 4004 /* Revision ID */ #error Wrong include file (ff.h). #endif @@ -109,7 +115,7 @@ #error Wrong sector size. #endif #if _MAX_SS != 512 -#define SS(fs) ((fs)->ssize) /* Multiple sector size */ +#define SS(fs) ((fs)->ssize) /* Variable sector size */ #else #define SS(fs) 512U /* Fixed sector size */ #endif @@ -130,10 +136,10 @@ #define ABORT(fs, res) { fp->flag |= FA__ERROR; LEAVE_FF(fs, res); } -/* File sharing feature */ -#if _FS_SHARE +/* File access control feature */ +#if _FS_LOCK #if _FS_READONLY -#error _FS_SHARE must be 0 on read-only cfg. +#error _FS_LOCK must be 0 on read-only cfg. #endif typedef struct { FATFS *fs; /* File ID 1, volume (NULL:blank entry) */ @@ -144,10 +150,6 @@ typedef struct { #endif -/* Misc definitions */ -#define LD_CLUST(dir) (((DWORD)LD_WORD(dir+DIR_FstClusHI)<<16) | LD_WORD(dir+DIR_FstClusLO)) -#define ST_CLUST(dir,cl) {ST_WORD(dir+DIR_FstClusLO, cl); ST_WORD(dir+DIR_FstClusHI, (DWORD)cl>>16);} - /* DBCS code ranges and SBCS extend char conversion table */ @@ -434,8 +436,10 @@ typedef struct { #define DIR_Name 0 /* Short file name (11) */ #define DIR_Attr 11 /* Attribute (1) */ #define DIR_NTres 12 /* NT flag (1) */ +#define DIR_CrtTimeTenth 13 /* Created time sub-second (1) */ #define DIR_CrtTime 14 /* Created time (2) */ #define DIR_CrtDate 16 /* Created date (2) */ +#define DIR_LstAccDate 18 /* Last accessed date (2) */ #define DIR_FstClusHI 20 /* Higher 16-bit of first cluster (2) */ #define DIR_WrtTime 22 /* Modified time (2) */ #define DIR_WrtDate 24 /* Modified date (2) */ @@ -449,17 +453,22 @@ typedef struct { #define SZ_DIR 32 /* Size of a directory entry */ #define LLE 0x40 /* Last long entry flag in LDIR_Ord */ #define DDE 0xE5 /* Deleted directory entry mark in DIR_Name[0] */ -#define NDDE 0x05 /* Replacement of a character collides with DDE */ +#define NDDE 0x05 /* Replacement of the character collides with DDE */ /*------------------------------------------------------------*/ -/* Work area */ +/* Module private work area */ +/*------------------------------------------------------------*/ +/* Note that uninitialized variables with static duration are +/ zeroed/nulled at start-up. If not, the compiler or start-up +/ routine is out of ANSI-C standard. +*/ #if _VOLUMES static FATFS *FatFs[_VOLUMES]; /* Pointer to the file system objects (logical drives) */ #else -#error Number of drives must not be 0. +#error Number of volumes must not be 0. #endif static @@ -470,28 +479,28 @@ static BYTE CurrVol; /* Current drive */ #endif -#if _FS_SHARE +#if _FS_LOCK static -FILESEM Files[_FS_SHARE]; /* File lock semaphores */ +FILESEM Files[_FS_LOCK]; /* File lock semaphores */ #endif -#if _USE_LFN == 0 /* No LFN */ +#if _USE_LFN == 0 /* No LFN feature */ #define DEF_NAMEBUF BYTE sfn[12] #define INIT_BUF(dobj) (dobj).fn = sfn #define FREE_BUF() -#elif _USE_LFN == 1 /* LFN with static LFN working buffer */ +#elif _USE_LFN == 1 /* LFN feature with static working buffer */ static WCHAR LfnBuf[_MAX_LFN+1]; #define DEF_NAMEBUF BYTE sfn[12] #define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = LfnBuf; } #define FREE_BUF() -#elif _USE_LFN == 2 /* LFN with dynamic LFN working buffer on the stack */ +#elif _USE_LFN == 2 /* LFN feature with dynamic working buffer on the stack */ #define DEF_NAMEBUF BYTE sfn[12]; WCHAR lbuf[_MAX_LFN+1] #define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = lbuf; } #define FREE_BUF() -#elif _USE_LFN == 3 /* LFN with dynamic LFN working buffer on the heap */ +#elif _USE_LFN == 3 /* LFN feature with dynamic working buffer on the heap */ #define DEF_NAMEBUF BYTE sfn[12]; WCHAR *lfn #define INIT_BUF(dobj) { lfn = ff_memalloc((_MAX_LFN + 1) * 2); \ if (!lfn) LEAVE_FF((dobj).fs, FR_NOT_ENOUGH_CORE); \ @@ -523,10 +532,10 @@ void mem_cpy (void* dst, const void* src, UINT cnt) { const BYTE *s = (const BYTE*)src; #if _WORD_ACCESS == 1 - while (cnt >= sizeof(int)) { + while (cnt >= sizeof (int)) { *(int*)d = *(int*)s; - d += sizeof(int); s += sizeof(int); - cnt -= sizeof(int); + d += sizeof (int); s += sizeof (int); + cnt -= sizeof (int); } #endif while (cnt--) @@ -581,7 +590,8 @@ void unlock_fs ( FRESULT res /* Result code to be returned */ ) { - if (res != FR_NOT_ENABLED && + if (fs && + res != FR_NOT_ENABLED && res != FR_INVALID_DRIVE && res != FR_INVALID_OBJECT && res != FR_TIMEOUT) { @@ -593,9 +603,9 @@ void unlock_fs ( /*-----------------------------------------------------------------------*/ -/* File shareing control functions */ +/* File lock control functions */ /*-----------------------------------------------------------------------*/ -#if _FS_SHARE +#if _FS_LOCK static FRESULT chk_lock ( /* Check if the file can be accessed */ @@ -606,7 +616,7 @@ FRESULT chk_lock ( /* Check if the file can be accessed */ UINT i, be; /* Search file semaphore table */ - for (i = be = 0; i < _FS_SHARE; i++) { + for (i = be = 0; i < _FS_LOCK; i++) { if (Files[i].fs) { /* Existing entry */ if (Files[i].fs == dj->fs && /* Check if the file matched with an open file */ Files[i].clu == dj->sclust && @@ -615,7 +625,7 @@ FRESULT chk_lock ( /* Check if the file can be accessed */ be++; } } - if (i == _FS_SHARE) /* The file is not opened */ + if (i == _FS_LOCK) /* The file is not opened */ return (be || acc == 2) ? FR_OK : FR_TOO_MANY_OPEN_FILES; /* Is there a blank entry for new file? */ /* The file has been opened. Reject any open against writing file and all write mode open */ @@ -624,14 +634,12 @@ FRESULT chk_lock ( /* Check if the file can be accessed */ static -int enq_lock ( /* Check if an entry is available for a new file */ - FATFS* fs /* File system object */ -) +int enq_lock (void) /* Check if an entry is available for a new file */ { UINT i; - for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ; - return (i == _FS_SHARE) ? 0 : 1; + for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ; + return (i == _FS_LOCK) ? 0 : 1; } @@ -644,15 +652,15 @@ UINT inc_lock ( /* Increment file open counter and returns its index (0:int erro UINT i; - for (i = 0; i < _FS_SHARE; i++) { /* Find the file */ + for (i = 0; i < _FS_LOCK; i++) { /* Find the file */ if (Files[i].fs == dj->fs && Files[i].clu == dj->sclust && Files[i].idx == dj->index) break; } - if (i == _FS_SHARE) { /* Not opened. Register it as new. */ - for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ; - if (i == _FS_SHARE) return 0; /* No space to register (int err) */ + if (i == _FS_LOCK) { /* Not opened. Register it as new. */ + for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ; + if (i == _FS_LOCK) return 0; /* No space to register (int err) */ Files[i].fs = dj->fs; Files[i].clu = dj->sclust; Files[i].idx = dj->index; @@ -676,7 +684,7 @@ FRESULT dec_lock ( /* Decrement file open counter */ FRESULT res; - if (--i < _FS_SHARE) { + if (--i < _FS_LOCK) { n = Files[i].ctr; if (n == 0x100) n = 0; if (n) n--; @@ -697,7 +705,7 @@ void clear_lock ( /* Clear lock entries of the volume */ { UINT i; - for (i = 0; i < _FS_SHARE; i++) { + for (i = 0; i < _FS_LOCK; i++) { if (Files[i].fs == fs) Files[i].fs = 0; } } @@ -776,7 +784,7 @@ FRESULT sync ( /* FR_OK: successful, FR_DISK_ERR: failed */ fs->fsi_flag = 0; } /* Make sure that no pending write process in the physical drive */ - if (disk_ioctl(fs->drv, CTRL_SYNC, (void*)0) != RES_OK) + if (disk_ioctl(fs->drv, CTRL_SYNC, 0) != RES_OK) res = FR_DISK_ERR; } @@ -819,7 +827,7 @@ DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status BYTE *p; - if (clst < 2 || clst >= fs->n_fatent) /* Chack range */ + if (clst < 2 || clst >= fs->n_fatent) /* Check range */ return 1; switch (fs->fs_type) { @@ -870,7 +878,7 @@ FRESULT put_fat ( } else { switch (fs->fs_type) { case FS_FAT12 : - bc = clst; bc += bc / 2; + bc = (UINT)clst; bc += bc / 2; res = move_window(fs, fs->fatbase + (bc / SS(fs))); if (res != FR_OK) break; p = &fs->win[bc % SS(fs)]; @@ -924,7 +932,7 @@ FRESULT remove_chain ( FRESULT res; DWORD nxt; #if _USE_ERASE - DWORD scl = clst, ecl = clst, resion[2]; + DWORD scl = clst, ecl = clst, rt[2]; #endif if (clst < 2 || clst >= fs->n_fatent) { /* Check range */ @@ -944,12 +952,12 @@ FRESULT remove_chain ( fs->fsi_flag = 1; } #if _USE_ERASE - if (ecl + 1 == nxt) { /* Next cluster is contiguous */ + if (ecl + 1 == nxt) { /* Is next cluster contiguous? */ ecl = nxt; - } else { /* End of contiguous clusters */ - resion[0] = clust2sect(fs, scl); /* Start sector */ - resion[1] = clust2sect(fs, ecl) + fs->csize - 1; /* End sector */ - disk_ioctl(fs->drv, CTRL_ERASE_SECTOR, resion); /* Erase the block */ + } else { /* End of contiguous clusters */ + rt[0] = clust2sect(fs, scl); /* Start sector */ + rt[1] = clust2sect(fs, ecl) + fs->csize - 1; /* End sector */ + disk_ioctl(fs->drv, CTRL_ERASE_SECTOR, rt); /* Erase the block */ scl = ecl = nxt; } #endif @@ -1058,7 +1066,7 @@ DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */ static FRESULT dir_sdi ( DIR *dj, /* Pointer to directory object */ - WORD idx /* Directory index number */ + WORD idx /* Index of directory table */ ) { DWORD clst; @@ -1100,7 +1108,7 @@ FRESULT dir_sdi ( /*-----------------------------------------------------------------------*/ -/* Directory handling - Move directory index next */ +/* Directory handling - Move directory table index next */ /*-----------------------------------------------------------------------*/ static @@ -1113,6 +1121,7 @@ FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT an WORD i; + stretch = stretch; /* To suppress warning on read-only cfg. */ i = dj->index + 1; if (!i || !dj->sect) /* Report EOT when index has reached 65535 */ return FR_NO_FILE; @@ -1166,6 +1175,40 @@ FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT an +/*-----------------------------------------------------------------------*/ +/* Directory handling - Load/Store start cluster number */ +/*-----------------------------------------------------------------------*/ + +static +DWORD ld_clust ( + FATFS *fs, /* Pointer to the fs object */ + BYTE *dir /* Pointer to the directory entry */ +) +{ + DWORD cl; + + cl = LD_WORD(dir+DIR_FstClusLO); + if (fs->fs_type == FS_FAT32) + cl |= (DWORD)LD_WORD(dir+DIR_FstClusHI) << 16; + + return cl; +} + + +#if !_FS_READONLY +static +void st_clust ( + BYTE *dir, /* Pointer to the directory entry */ + DWORD cl /* Value to be set */ +) +{ + ST_WORD(dir+DIR_FstClusLO, cl); + ST_WORD(dir+DIR_FstClusHI, cl >> 16); +} +#endif + + + /*-----------------------------------------------------------------------*/ /* LFN handling - Test/Pick/Fit an LFN segment from/to directory entry */ /*-----------------------------------------------------------------------*/ @@ -1777,7 +1820,7 @@ FRESULT create_name ( if (c >= 0x80) { /* Extended char? */ b |= 3; /* Eliminate NT flag */ #ifdef _EXCVT - c = excvt[c-0x80]; /* Upper conversion (SBCS) */ + c = excvt[c - 0x80]; /* Upper conversion (SBCS) */ #else #if !_DF1S /* ASCII only cfg */ return FR_INVALID_NAME; @@ -1933,7 +1976,6 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ if ((UINT)*path < ' ') { /* Nul path means the start directory itself */ res = dir_sdi(dj, 0); dj->dir = 0; - } else { /* Follow path */ for (;;) { res = create_name(dj, &path); /* Get a segment */ @@ -1941,7 +1983,7 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ res = dir_find(dj); /* Find it */ ns = *(dj->fn+NS); if (res != FR_OK) { /* Failed to find the object */ - if (res != FR_NO_FILE) break; /* Abort if any hard error occured */ + if (res != FR_NO_FILE) break; /* Abort if any hard error occurred */ /* Object not found */ if (_FS_RPATH && (ns & NS_DOT)) { /* If dot entry is not exit */ dj->sclust = 0; dj->dir = 0; /* It is the root dir */ @@ -1957,7 +1999,7 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ if (!(dir[DIR_Attr] & AM_DIR)) { /* Cannot follow because it is a file */ res = FR_NO_PATH; break; } - dj->sclust = LD_CLUST(dir); + dj->sclust = ld_clust(dj->fs, dir); } } @@ -1968,11 +2010,11 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ /*-----------------------------------------------------------------------*/ -/* Load boot record and check if it is an FAT boot record */ +/* Load a sector and check if it is an FAT Volume Boot Record */ /*-----------------------------------------------------------------------*/ static -BYTE check_fs ( /* 0:The FAT BR, 1:Valid BR but not an FAT, 2:Not a BR, 3:Disk error */ +BYTE check_fs ( /* 0:FAT-VBR, 1:Any BR but not FAT, 2:Not a BR, 3:Disk error */ FATFS *fs, /* File system object */ DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */ ) @@ -2001,10 +2043,10 @@ static FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */ const TCHAR **path, /* Pointer to pointer to the path name (drive number) */ FATFS **rfs, /* Pointer to pointer to the found file system object */ - BYTE chk_wp /* !=0: Check media write protection for write access */ + BYTE wmode /* !=0: Check write protection for write access */ ) { - BYTE fmt, b, *tbl; + BYTE fmt, b, pi, *tbl; UINT vol; DSTATUS stat; DWORD bsect, fasize, tsect, sysect, nclst, szbfat; @@ -2012,6 +2054,7 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */ const TCHAR *p = *path; FATFS *fs; + /* Get logical drive number from the path name */ vol = p[0] - '0'; /* Is there a drive number? */ if (vol <= 9 && p[1] == ':') { /* Found a drive number, get and strip it */ @@ -2024,55 +2067,56 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */ #endif } - /* Check if the logical drive is valid or not */ + /* Check if the file system object is valid or not */ + *rfs = 0; if (vol >= _VOLUMES) /* Is the drive number valid? */ return FR_INVALID_DRIVE; - *rfs = fs = FatFs[vol]; /* Return pointer to the corresponding file system object */ + fs = FatFs[vol]; /* Get corresponding file system object */ if (!fs) return FR_NOT_ENABLED; /* Is the file system object available? */ ENTER_FF(fs); /* Lock file system */ - if (fs->fs_type) { /* If the logical drive has been mounted */ + *rfs = fs; /* Return pointer to the corresponding file system object */ + if (fs->fs_type) { /* If the volume has been mounted */ stat = disk_status(fs->drv); if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized (has not been changed), */ -#if !_FS_READONLY - if (chk_wp && (stat & STA_PROTECT)) /* Check write protection if needed */ + if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) /* Check write protection if needed */ return FR_WRITE_PROTECTED; -#endif return FR_OK; /* The file system object is valid */ } } - /* The logical drive must be mounted. */ - /* Following code attempts to mount a volume. (analyze BPB and initialize the fs object) */ + /* The file system object is not valid. */ + /* Following code attempts to mount the volume. (analyze BPB and initialize the fs object) */ fs->fs_type = 0; /* Clear the file system object */ - fs->drv = (BYTE)LD2PD(vol); /* Bind the logical drive and a physical drive */ - stat = disk_initialize(fs->drv); /* Initialize low level disk I/O layer */ + fs->drv = LD2PD(vol); /* Bind the logical drive and a physical drive */ + stat = disk_initialize(fs->drv); /* Initialize the physical drive */ if (stat & STA_NOINIT) /* Check if the initialization succeeded */ - return FR_NOT_READY; /* Failed to initialize due to no media or hard error */ + return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */ + if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) /* Check disk write protection if needed */ + return FR_WRITE_PROTECTED; #if _MAX_SS != 512 /* Get disk sector size (variable sector size cfg only) */ if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &fs->ssize) != RES_OK) return FR_DISK_ERR; #endif -#if !_FS_READONLY - if (chk_wp && (stat & STA_PROTECT)) /* Check disk write protection if needed */ - return FR_WRITE_PROTECTED; -#endif - /* Search FAT partition on the drive. Supports only generic partitioning, FDISK and SFD. */ - fmt = check_fs(fs, bsect = 0); /* Check sector 0 if it is a VBR */ - if (fmt == 1) { /* Not an FAT-VBR, the disk may be partitioned */ - /* Check the partition listed in top of the partition table */ - tbl = &fs->win[MBR_Table + LD2PT(vol) * SZ_PTE];/* Partition table */ - if (tbl[4]) { /* Is the partition existing? */ - bsect = LD_DWORD(&tbl[8]); /* Partition offset in LBA */ - fmt = check_fs(fs, bsect); /* Check the partition */ + /* Search FAT partition on the drive. Supports only generic partitions, FDISK and SFD. */ + fmt = check_fs(fs, bsect = 0); /* Load sector 0 and check if it is an FAT-VBR (in SFD) */ + if (LD2PT(vol) && !fmt) fmt = 1; /* Force non-SFD if the volume is forced partition */ + if (fmt == 1) { /* Not an FAT-VBR, the physical drive can be partitioned */ + /* Check the partition listed in the partition table */ + pi = LD2PT(vol); + if (pi) pi--; + tbl = &fs->win[MBR_Table + pi * SZ_PTE];/* Partition table */ + if (tbl[4]) { /* Is the partition existing? */ + bsect = LD_DWORD(&tbl[8]); /* Partition offset in LBA */ + fmt = check_fs(fs, bsect); /* Check the partition */ } } if (fmt == 3) return FR_DISK_ERR; - if (fmt) return FR_NO_FILESYSTEM; /* No FAT volume is found */ + if (fmt) return FR_NO_FILESYSTEM; /* No FAT volume is found */ - /* Following code initializes the file system object */ + /* An FAT volume is found. Following code initializes the file system object */ if (LD_WORD(fs->win+BPB_BytsPerSec) != SS(fs)) /* (BPB_BytsPerSec must be equal to the physical sector size) */ return FR_NO_FILESYSTEM; @@ -2148,7 +2192,7 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */ #if _FS_RPATH fs->cdir = 0; /* Current directory (root dir) */ #endif -#if _FS_SHARE /* Clear file lock semaphores */ +#if _FS_LOCK /* Clear file lock semaphores */ clear_lock(fs); #endif @@ -2164,16 +2208,19 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */ static FRESULT validate ( /* FR_OK(0): The object is valid, !=0: Invalid */ - FATFS *fs, /* Pointer to the file system object */ - WORD id /* Member id of the target object to be checked */ + void* obj /* Pointer to the object FIL/DIR to check validity */ ) { - if (!fs || !fs->fs_type || fs->id != id) + FIL *fil; + + + fil = (FIL*)obj; /* Assuming offset of fs and id in the FIL/DIR is identical */ + if (!fil->fs || !fil->fs->fs_type || fil->fs->id != fil->id) return FR_INVALID_OBJECT; - ENTER_FF(fs); /* Lock file system */ + ENTER_FF(fil->fs); /* Lock file system */ - if (disk_status(fs->drv) & STA_NOINIT) + if (disk_status(fil->fs->drv) & STA_NOINIT) return FR_NOT_READY; return FR_OK; @@ -2202,27 +2249,27 @@ FRESULT f_mount ( FATFS *rfs; - if (vol >= _VOLUMES) /* Check if the drive number is valid */ + if (vol >= _VOLUMES) /* Check if the drive number is valid */ return FR_INVALID_DRIVE; - rfs = FatFs[vol]; /* Get current fs object */ + rfs = FatFs[vol]; /* Get current fs object */ if (rfs) { -#if _FS_SHARE +#if _FS_LOCK clear_lock(rfs); #endif -#if _FS_REENTRANT /* Discard sync object of the current volume */ +#if _FS_REENTRANT /* Discard sync object of the current volume */ if (!ff_del_syncobj(rfs->sobj)) return FR_INT_ERR; #endif - rfs->fs_type = 0; /* Clear old fs object */ + rfs->fs_type = 0; /* Clear old fs object */ } if (fs) { - fs->fs_type = 0; /* Clear new fs object */ -#if _FS_REENTRANT /* Create sync object for the new volume */ + fs->fs_type = 0; /* Clear new fs object */ +#if _FS_REENTRANT /* Create sync object for the new volume */ if (!ff_cre_syncobj(vol, &fs->sobj)) return FR_INT_ERR; #endif } - FatFs[vol] = fs; /* Register new fs object */ + FatFs[vol] = fs; /* Register new fs object */ return FR_OK; } @@ -2246,6 +2293,7 @@ FRESULT f_open ( DEF_NAMEBUF; + if (!fp) return FR_INVALID_OBJECT; fp->fs = 0; /* Clear file object */ #if !_FS_READONLY @@ -2255,103 +2303,104 @@ FRESULT f_open ( mode &= FA_READ; res = chk_mounted(&path, &dj.fs, 0); #endif - INIT_BUF(dj); - if (res == FR_OK) + if (res == FR_OK) { + INIT_BUF(dj); res = follow_path(&dj, path); /* Follow the file path */ - dir = dj.dir; - + dir = dj.dir; #if !_FS_READONLY /* R/W configuration */ - if (res == FR_OK) { - if (!dir) /* Current dir itself */ - res = FR_INVALID_NAME; -#if _FS_SHARE - else - res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0); + if (res == FR_OK) { + if (!dir) /* Current dir itself */ + res = FR_INVALID_NAME; +#if _FS_LOCK + else + res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0); #endif - } - /* Create or Open a file */ - if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) { - DWORD dw, cl; - - if (res != FR_OK) { /* No file, create new */ - if (res == FR_NO_FILE) /* There is no file to open, create a new entry */ -#if _FS_SHARE - res = enq_lock(dj.fs) ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES; + } + /* Create or Open a file */ + if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) { + DWORD dw, cl; + + if (res != FR_OK) { /* No file, create new */ + if (res == FR_NO_FILE) /* There is no file to open, create a new entry */ +#if _FS_LOCK + res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES; #else - res = dir_register(&dj); + res = dir_register(&dj); #endif - mode |= FA_CREATE_ALWAYS; /* File is created */ - dir = dj.dir; /* New entry */ - } - else { /* Any object is already existing */ - if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) { /* Cannot overwrite it (R/O or DIR) */ - res = FR_DENIED; - } else { - if (mode & FA_CREATE_NEW) /* Cannot create as new file */ - res = FR_EXIST; + mode |= FA_CREATE_ALWAYS; /* File is created */ + dir = dj.dir; /* New entry */ } - } - if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate it if overwrite mode */ - dw = get_fattime(); /* Created time */ - ST_DWORD(dir+DIR_CrtTime, dw); - dir[DIR_Attr] = 0; /* Reset attribute */ - ST_DWORD(dir+DIR_FileSize, 0); /* size = 0 */ - cl = LD_CLUST(dir); /* Get start cluster */ - ST_CLUST(dir, 0); /* cluster = 0 */ - dj.fs->wflag = 1; - if (cl) { /* Remove the cluster chain if exist */ - dw = dj.fs->winsect; - res = remove_chain(dj.fs, cl); - if (res == FR_OK) { - dj.fs->last_clust = cl - 1; /* Reuse the cluster hole */ - res = move_window(dj.fs, dw); + else { /* Any object is already existing */ + if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) { /* Cannot overwrite it (R/O or DIR) */ + res = FR_DENIED; + } else { + if (mode & FA_CREATE_NEW) /* Cannot create as new file */ + res = FR_EXIST; + } + } + if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate it if overwrite mode */ + dw = get_fattime(); /* Created time */ + ST_DWORD(dir+DIR_CrtTime, dw); + dir[DIR_Attr] = 0; /* Reset attribute */ + ST_DWORD(dir+DIR_FileSize, 0); /* size = 0 */ + cl = ld_clust(dj.fs, dir); /* Get start cluster */ + st_clust(dir, 0); /* cluster = 0 */ + dj.fs->wflag = 1; + if (cl) { /* Remove the cluster chain if exist */ + dw = dj.fs->winsect; + res = remove_chain(dj.fs, cl); + if (res == FR_OK) { + dj.fs->last_clust = cl - 1; /* Reuse the cluster hole */ + res = move_window(dj.fs, dw); + } } } } - } - else { /* Open an existing file */ - if (res == FR_OK) { /* Follow succeeded */ - if (dir[DIR_Attr] & AM_DIR) { /* It is a directory */ - res = FR_NO_FILE; - } else { - if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */ - res = FR_DENIED; + else { /* Open an existing file */ + if (res == FR_OK) { /* Follow succeeded */ + if (dir[DIR_Attr] & AM_DIR) { /* It is a directory */ + res = FR_NO_FILE; + } else { + if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */ + res = FR_DENIED; + } } } - } - if (res == FR_OK) { - if (mode & FA_CREATE_ALWAYS) /* Set file change flag if created or overwritten */ - mode |= FA__WRITTEN; - fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */ - fp->dir_ptr = dir; -#if _FS_SHARE - fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0); - if (!fp->lockid) res = FR_INT_ERR; + if (res == FR_OK) { + if (mode & FA_CREATE_ALWAYS) /* Set file change flag if created or overwritten */ + mode |= FA__WRITTEN; + fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */ + fp->dir_ptr = dir; +#if _FS_LOCK + fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0); + if (!fp->lockid) res = FR_INT_ERR; #endif - } + } #else /* R/O configuration */ - if (res == FR_OK) { /* Follow succeeded */ - if (!dir) { /* Current dir itself */ - res = FR_INVALID_NAME; - } else { - if (dir[DIR_Attr] & AM_DIR) /* It is a directory */ - res = FR_NO_FILE; + if (res == FR_OK) { /* Follow succeeded */ + dir = dj.dir; + if (!dir) { /* Current dir itself */ + res = FR_INVALID_NAME; + } else { + if (dir[DIR_Attr] & AM_DIR) /* It is a directory */ + res = FR_NO_FILE; + } } - } #endif - FREE_BUF(); + FREE_BUF(); - if (res == FR_OK) { - fp->flag = mode; /* File access mode */ - fp->sclust = LD_CLUST(dir); /* File start cluster */ - fp->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */ - fp->fptr = 0; /* File pointer */ - fp->dsect = 0; + if (res == FR_OK) { + fp->flag = mode; /* File access mode */ + fp->sclust = ld_clust(dj.fs, dir); /* File start cluster */ + fp->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */ + fp->fptr = 0; /* File pointer */ + fp->dsect = 0; #if _USE_FASTSEEK - fp->cltbl = 0; /* Normal seek mode */ + fp->cltbl = 0; /* Normal seek mode */ #endif - fp->fs = dj.fs; fp->id = dj.fs->id; /* Validate file object */ + fp->fs = dj.fs; fp->id = dj.fs->id; /* Validate file object */ + } } LEAVE_FF(dj.fs, res); @@ -2377,9 +2426,9 @@ FRESULT f_read ( BYTE csect, *rbuff = buff; - *br = 0; /* Initialize byte counter */ + *br = 0; /* Clear read byte counter */ - res = validate(fp->fs, fp->id); /* Check validity */ + res = validate(fp); /* Check validity */ if (res != FR_OK) LEAVE_FF(fp->fs, res); if (fp->flag & FA__ERROR) /* Aborted file? */ LEAVE_FF(fp->fs, FR_INT_ERR); @@ -2443,7 +2492,7 @@ FRESULT f_read ( #endif fp->dsect = sect; } - rcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs)); /* Get partial sector data from sector buffer */ + rcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs)); /* Get partial sector data from sector buffer */ if (rcnt > btr) rcnt = btr; #if _FS_TINY if (move_window(fp->fs, fp->dsect)) /* Move sector window */ @@ -2479,9 +2528,9 @@ FRESULT f_write ( BYTE csect; - *bw = 0; /* Initialize byte counter */ + *bw = 0; /* Clear write byte counter */ - res = validate(fp->fs, fp->id); /* Check validity */ + res = validate(fp); /* Check validity */ if (res != FR_OK) LEAVE_FF(fp->fs, res); if (fp->flag & FA__ERROR) /* Aborted file? */ LEAVE_FF(fp->fs, FR_INT_ERR); @@ -2558,7 +2607,7 @@ FRESULT f_write ( #endif fp->dsect = sect; } - wcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */ + wcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */ if (wcnt > btw) wcnt = btw; #if _FS_TINY if (move_window(fp->fs, fp->dsect)) /* Move sector window */ @@ -2593,7 +2642,7 @@ FRESULT f_sync ( BYTE *dir; - res = validate(fp->fs, fp->id); /* Check validity of the object */ + res = validate(fp); /* Check validity of the object */ if (res == FR_OK) { if (fp->flag & FA__WRITTEN) { /* Has the file been written? */ #if !_FS_TINY /* Write-back dirty buffer */ @@ -2609,9 +2658,10 @@ FRESULT f_sync ( dir = fp->dir_ptr; dir[DIR_Attr] |= AM_ARC; /* Set archive bit */ ST_DWORD(dir+DIR_FileSize, fp->fsize); /* Update file size */ - ST_CLUST(dir, fp->sclust); /* Update start cluster */ + st_clust(dir, fp->sclust); /* Update start cluster */ tim = get_fattime(); /* Update updated time */ ST_DWORD(dir+DIR_WrtTime, tim); + ST_WORD(dir+DIR_LstAccDate, 0); fp->flag &= ~FA__WRITTEN; fp->fs->wflag = 1; res = sync(fp->fs); @@ -2637,21 +2687,26 @@ FRESULT f_close ( { FRESULT res; -#if _FS_READONLY - FATFS *fs = fp->fs; - res = validate(fs, fp->id); - if (res == FR_OK) fp->fs = 0; /* Discard file object */ - LEAVE_FF(fs, res); +#if _FS_READONLY + res = validate(fp); + { +#if _FS_REENTRANT + FATFS *fs = fp->fs; +#endif + if (res == FR_OK) fp->fs = 0; /* Discard file object */ + LEAVE_FF(fs, res); + } #else res = f_sync(fp); /* Flush cached data */ -#if _FS_SHARE +#if _FS_LOCK if (res == FR_OK) { /* Decrement open counter */ #if _FS_REENTRANT - res = validate(fp->fs, fp->id); + FATFS *fs = fp->fs;; + res = validate(fp); if (res == FR_OK) { - res = dec_lock(fp->lockid); - unlock_fs(fp->fs, FR_OK); + res = dec_lock(fp->lockid); + unlock_fs(fs, FR_OK); } #else res = dec_lock(fp->lockid); @@ -2704,7 +2759,7 @@ FRESULT f_chdir ( dj.fs->cdir = dj.sclust; /* Start directory itself */ } else { if (dj.dir[DIR_Attr] & AM_DIR) /* Reached to the directory */ - dj.fs->cdir = LD_CLUST(dj.dir); + dj.fs->cdir = ld_clust(dj.fs, dj.dir); else res = FR_NO_PATH; /* Reached but a file */ } @@ -2742,14 +2797,14 @@ FRESULT f_getcwd ( if (res != FR_OK) break; res = dir_read(&dj); if (res != FR_OK) break; - dj.sclust = LD_CLUST(dj.dir); /* Goto parent dir */ + dj.sclust = ld_clust(dj.fs, dj.dir); /* Goto parent dir */ res = dir_sdi(&dj, 0); if (res != FR_OK) break; do { /* Find the entry links to the child dir */ res = dir_read(&dj); if (res != FR_OK) break; - if (ccl == LD_CLUST(dj.dir)) break; /* Found the entry */ - res = dir_next(&dj, 0); + if (ccl == ld_clust(dj.fs, dj.dir)) break; /* Found the entry */ + res = dir_next(&dj, 0); } while (res == FR_OK); if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */ if (res != FR_OK) break; @@ -2803,7 +2858,7 @@ FRESULT f_lseek ( FRESULT res; - res = validate(fp->fs, fp->id); /* Check validity of the object */ + res = validate(fp); /* Check validity of the object */ if (res != FR_OK) LEAVE_FF(fp->fs, res); if (fp->flag & FA__ERROR) /* Check abort flag */ LEAVE_FF(fp->fs, FR_INT_ERR); @@ -2959,10 +3014,14 @@ FRESULT f_opendir ( ) { FRESULT res; + FATFS *fs; DEF_NAMEBUF; + if (!dj) return FR_INVALID_OBJECT; + res = chk_mounted(&path, &dj->fs, 0); + fs = dj->fs; if (res == FR_OK) { INIT_BUF(*dj); res = follow_path(dj, path); /* Follow the path to the directory */ @@ -2970,20 +3029,23 @@ FRESULT f_opendir ( if (res == FR_OK) { /* Follow completed */ if (dj->dir) { /* It is not the root dir */ if (dj->dir[DIR_Attr] & AM_DIR) { /* The object is a directory */ - dj->sclust = LD_CLUST(dj->dir); + dj->sclust = ld_clust(fs, dj->dir); } else { /* The object is not a directory */ res = FR_NO_PATH; } } if (res == FR_OK) { - dj->id = dj->fs->id; + dj->id = fs->id; res = dir_sdi(dj, 0); /* Rewind dir */ } } if (res == FR_NO_FILE) res = FR_NO_PATH; + if (res != FR_OK) dj->fs = 0; /* Invalidate the dir object if function faild */ + } else { + dj->fs = 0; } - LEAVE_FF(dj->fs, res); + LEAVE_FF(fs, res); } @@ -3002,7 +3064,7 @@ FRESULT f_readdir ( DEF_NAMEBUF; - res = validate(dj->fs, dj->id); /* Check validity of the object */ + res = validate(dj); /* Check validity of the object */ if (res == FR_OK) { if (!fno) { res = dir_sdi(dj, 0); /* Rewind the directory object */ @@ -3075,6 +3137,7 @@ FRESULT f_getfree ( ) { FRESULT res; + FATFS *fs; DWORD n, clst, sect, stat; UINT i; BYTE fat, *p; @@ -3082,32 +3145,33 @@ FRESULT f_getfree ( /* Get drive number */ res = chk_mounted(&path, fatfs, 0); + fs = *fatfs; if (res == FR_OK) { /* If free_clust is valid, return it without full cluster scan */ - if ((*fatfs)->free_clust <= (*fatfs)->n_fatent - 2) { - *nclst = (*fatfs)->free_clust; + if (fs->free_clust <= fs->n_fatent - 2) { + *nclst = fs->free_clust; } else { /* Get number of free clusters */ - fat = (*fatfs)->fs_type; + fat = fs->fs_type; n = 0; if (fat == FS_FAT12) { clst = 2; do { - stat = get_fat(*fatfs, clst); + stat = get_fat(fs, clst); if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } if (stat == 1) { res = FR_INT_ERR; break; } if (stat == 0) n++; - } while (++clst < (*fatfs)->n_fatent); + } while (++clst < fs->n_fatent); } else { - clst = (*fatfs)->n_fatent; - sect = (*fatfs)->fatbase; + clst = fs->n_fatent; + sect = fs->fatbase; i = 0; p = 0; do { if (!i) { - res = move_window(*fatfs, sect++); + res = move_window(fs, sect++); if (res != FR_OK) break; - p = (*fatfs)->win; - i = SS(*fatfs); + p = fs->win; + i = SS(fs); } if (fat == FS_FAT16) { if (LD_WORD(p) == 0) n++; @@ -3118,12 +3182,12 @@ FRESULT f_getfree ( } } while (--clst); } - (*fatfs)->free_clust = n; - if (fat == FS_FAT32) (*fatfs)->fsi_flag = 1; + fs->free_clust = n; + if (fat == FS_FAT32) fs->fsi_flag = 1; *nclst = n; } } - LEAVE_FF(*fatfs, res); + LEAVE_FF(fs, res); } @@ -3141,7 +3205,9 @@ FRESULT f_truncate ( DWORD ncl; - res = validate(fp->fs, fp->id); /* Check validity of the object */ + if (!fp) return FR_INVALID_OBJECT; + + res = validate(fp); /* Check validity of the object */ if (res == FR_OK) { if (fp->flag & FA__ERROR) { /* Check abort flag */ res = FR_INT_ERR; @@ -3198,7 +3264,7 @@ FRESULT f_unlink ( res = follow_path(&dj, path); /* Follow the file path */ if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) res = FR_INVALID_NAME; /* Cannot remove dot entry */ -#if _FS_SHARE +#if _FS_LOCK if (res == FR_OK) res = chk_lock(&dj, 2); /* Cannot remove open file */ #endif if (res == FR_OK) { /* The object is accessible */ @@ -3209,19 +3275,19 @@ FRESULT f_unlink ( if (dir[DIR_Attr] & AM_RDO) res = FR_DENIED; /* Cannot remove R/O object */ } - dclst = LD_CLUST(dir); + dclst = ld_clust(dj.fs, dir); if (res == FR_OK && (dir[DIR_Attr] & AM_DIR)) { /* Is it a sub-dir? */ if (dclst < 2) { res = FR_INT_ERR; } else { - mem_cpy(&sdj, &dj, sizeof(DIR)); /* Check if the sub-dir is empty or not */ + mem_cpy(&sdj, &dj, sizeof (DIR)); /* Check if the sub-dir is empty or not */ sdj.sclust = dclst; res = dir_sdi(&sdj, 2); /* Exclude dot entries */ if (res == FR_OK) { res = dir_read(&sdj); - if (res == FR_OK /* Not empty dir */ + if (res == FR_OK /* Not empty dir */ #if _FS_RPATH - || dclst == sdj.fs->cdir /* Current dir */ + || dclst == dj.fs->cdir /* Current dir */ #endif ) res = FR_DENIED; if (res == FR_NO_FILE) res = FR_OK; /* Empty */ @@ -3283,12 +3349,12 @@ FRESULT f_mkdir ( dir[DIR_Name] = '.'; dir[DIR_Attr] = AM_DIR; ST_DWORD(dir+DIR_WrtTime, tim); - ST_CLUST(dir, dcl); + st_clust(dir, dcl); mem_cpy(dir+SZ_DIR, dir, SZ_DIR); /* Create ".." entry */ dir[33] = '.'; pcl = dj.sclust; if (dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase) pcl = 0; - ST_CLUST(dir+SZ_DIR, pcl); + st_clust(dir+SZ_DIR, pcl); for (n = dj.fs->csize; n; n--) { /* Write dot entries and clear following sectors */ dj.fs->winsect = dsc++; dj.fs->wflag = 1; @@ -3304,7 +3370,7 @@ FRESULT f_mkdir ( dir = dj.dir; dir[DIR_Attr] = AM_DIR; /* Attribute */ ST_DWORD(dir+DIR_WrtTime, tim); /* Created time */ - ST_CLUST(dir, dcl); /* Table start cluster */ + st_clust(dir, dcl); /* Table start cluster */ dj.fs->wflag = 1; res = sync(dj.fs); } @@ -3424,7 +3490,7 @@ FRESULT f_rename ( res = follow_path(&djo, path_old); /* Check old object */ if (_FS_RPATH && res == FR_OK && (djo.fn[NS] & NS_DOT)) res = FR_INVALID_NAME; -#if _FS_SHARE +#if _FS_LOCK if (res == FR_OK) res = chk_lock(&djo, 2); #endif if (res == FR_OK) { /* Old object is found */ @@ -3432,11 +3498,11 @@ FRESULT f_rename ( res = FR_NO_FILE; } else { mem_cpy(buf, djo.dir+DIR_Attr, 21); /* Save the object information except for name */ - mem_cpy(&djn, &djo, sizeof(DIR)); /* Check new object */ + mem_cpy(&djn, &djo, sizeof (DIR)); /* Check new object */ res = follow_path(&djn, path_new); if (res == FR_OK) res = FR_EXIST; /* The new object name is already existing */ if (res == FR_NO_FILE) { /* Is it a valid path and no name collision? */ -/* Start critical section that any interruption or error can cause cross-link */ +/* Start critical section that an interruption or error can cause cross-link */ res = dir_register(&djn); /* Register the new entry */ if (res == FR_OK) { dir = djn.dir; /* Copy object information except for name */ @@ -3444,16 +3510,16 @@ FRESULT f_rename ( dir[DIR_Attr] = buf[0] | AM_ARC; djo.fs->wflag = 1; if (djo.sclust != djn.sclust && (dir[DIR_Attr] & AM_DIR)) { /* Update .. entry in the directory if needed */ - dw = clust2sect(djn.fs, LD_CLUST(dir)); + dw = clust2sect(djo.fs, ld_clust(djo.fs, dir)); if (!dw) { res = FR_INT_ERR; } else { - res = move_window(djn.fs, dw); - dir = djn.fs->win+SZ_DIR; /* .. entry */ + res = move_window(djo.fs, dw); + dir = djo.fs->win+SZ_DIR; /* .. entry */ if (res == FR_OK && dir[1] == '.') { - dw = (djn.fs->fs_type == FS_FAT32 && djn.sclust == djn.fs->dirbase) ? 0 : djn.sclust; - ST_CLUST(dir, dw); - djn.fs->wflag = 1; + dw = (djo.fs->fs_type == FS_FAT32 && djn.sclust == djo.fs->dirbase) ? 0 : djn.sclust; + st_clust(dir, dw); + djo.fs->wflag = 1; } } } @@ -3497,9 +3563,11 @@ FRESULT f_forward ( BYTE csect; - *bf = 0; /* Initialize byte counter */ + *bf = 0; /* Clear transfer byte counter */ + + if (!fp) return FR_INVALID_OBJECT; - res = validate(fp->fs, fp->id); /* Check validity of the object */ + res = validate(fp); /* Check validity of the object */ if (res != FR_OK) LEAVE_FF(fp->fs, res); if (fp->flag & FA__ERROR) /* Check error flag */ LEAVE_FF(fp->fs, FR_INT_ERR); @@ -3555,10 +3623,10 @@ FRESULT f_mkfs ( { static const WORD vst[] = { 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 0}; static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512}; - BYTE fmt, md, *tbl; + BYTE fmt, md, sys, *tbl, pdrv, part; DWORD n_clst, vs, n, wsect; UINT i; - DWORD b_vol, b_fat, b_dir, b_data; /* Offset (LBA) */ + DWORD b_vol, b_fat, b_dir, b_data; /* LBA */ DWORD n_vol, n_rsv, n_fat, n_dir; /* Size */ FATFS *fs; DSTATUS stat; @@ -3566,25 +3634,39 @@ FRESULT f_mkfs ( /* Check mounted drive and clear work area */ if (drv >= _VOLUMES) return FR_INVALID_DRIVE; + if (sfd > 1) return FR_INVALID_PARAMETER; + if (au & (au - 1)) return FR_INVALID_PARAMETER; fs = FatFs[drv]; if (!fs) return FR_NOT_ENABLED; fs->fs_type = 0; - drv = LD2PD(drv); + pdrv = LD2PD(drv); /* Physical drive */ + part = LD2PT(drv); /* Partition (0:auto detect, 1-4:get from partition table)*/ /* Get disk statics */ - stat = disk_initialize(drv); + stat = disk_initialize(pdrv); if (stat & STA_NOINIT) return FR_NOT_READY; if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; #if _MAX_SS != 512 /* Get disk sector size */ - if (disk_ioctl(drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK) + if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > _MAX_SS) return FR_DISK_ERR; #endif - if (disk_ioctl(drv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128) - return FR_DISK_ERR; - b_vol = (sfd) ? 0 : 63; /* Volume start sector */ - n_vol -= b_vol; - if (au & (au - 1)) au = 0; /* Check validity of the AU size */ - if (!au) { /* AU auto selection */ + if (_MULTI_PARTITION && part) { + /* Get partition information from partition table in the MBR */ + if (disk_read(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR; + if (LD_WORD(fs->win+BS_55AA) != 0xAA55) return FR_MKFS_ABORTED; + tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE]; + if (!tbl[4]) return FR_MKFS_ABORTED; /* No partition? */ + b_vol = LD_DWORD(tbl+8); /* Volume start sector */ + n_vol = LD_DWORD(tbl+12); /* Volume size */ + } else { + /* Create a partition in this function */ + if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128) + return FR_DISK_ERR; + b_vol = (sfd) ? 0 : 63; /* Volume start sector */ + n_vol -= b_vol; /* Volume size */ + } + + if (!au) { /* AU auto selection */ vs = n_vol / (2000 / (SS(fs) / 512)); for (i = 0; vs < vst[i]; i++) ; au = cst[i]; @@ -3593,7 +3675,7 @@ FRESULT f_mkfs ( if (au == 0) au = 1; if (au > 128) au = 128; - /* Pre-compute number of clusters and FAT syb-type */ + /* Pre-compute number of clusters and FAT sub-type */ n_clst = n_vol / au; fmt = FS_FAT12; if (n_clst >= MIN_FAT16) fmt = FS_FAT16; @@ -3613,10 +3695,10 @@ FRESULT f_mkfs ( b_fat = b_vol + n_rsv; /* FAT area start sector */ b_dir = b_fat + n_fat * N_FATS; /* Directory area start sector */ b_data = b_dir + n_dir; /* Data area start sector */ - if (n_vol < b_data + au) return FR_MKFS_ABORTED; /* Too small volume */ + if (n_vol < b_data + au - b_vol) return FR_MKFS_ABORTED; /* Too small volume */ /* Align data start sector to erase block boundary (for flash memory media) */ - if (disk_ioctl(drv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1; + if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1; n = (b_data + n - 1) & ~(n - 1); /* Next nearest erase block from current data start */ n = (n - b_data) / N_FATS; if (fmt == FS_FAT32) { /* FAT32: Move FAT offset */ @@ -3632,36 +3714,42 @@ FRESULT f_mkfs ( || (fmt == FS_FAT32 && n_clst < MIN_FAT32)) return FR_MKFS_ABORTED; - /* Create partition table if required */ - if (sfd) { /* No partition table (SFD) */ - md = 0xF0; - } else { /* With partition table (FDISK) */ - DWORD n_disk = b_vol + n_vol; - - mem_set(fs->win, 0, SS(fs)); - tbl = fs->win+MBR_Table; - ST_DWORD(tbl, 0x00010180); /* Partition start in CHS */ - if (n_disk < 63UL * 255 * 1024) { /* Partition end in CHS */ - n_disk = n_disk / 63 / 255; - tbl[7] = (BYTE)n_disk; - tbl[6] = (BYTE)((n_disk >> 2) | 63); - } else { - ST_WORD(&tbl[6], 0xFFFF); /* CHS saturated */ - } - tbl[5] = 254; - if (fmt != FS_FAT32) /* System ID */ - tbl[4] = (n_vol < 0x10000) ? 0x04 : 0x06; - else - tbl[4] = 0x0c; - ST_DWORD(tbl+8, 63); /* Partition start in LBA */ - ST_DWORD(tbl+12, n_vol); /* Partition size in LBA */ - ST_WORD(fs->win+BS_55AA, 0xAA55); /* MBR signature */ - if (disk_write(drv, fs->win, 0, 1) != RES_OK) /* Put the MBR into first physical sector */ - return FR_DISK_ERR; + switch (fmt) { /* Determine system ID for partition table */ + case FS_FAT12: sys = 0x01; break; + case FS_FAT16: sys = (n_vol < 0x10000) ? 0x04 : 0x06; break; + default: sys = 0x0C; + } + + if (_MULTI_PARTITION && part) { + /* Update system ID in the partition table */ + tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE]; + tbl[4] = sys; + if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR; md = 0xF8; + } else { + if (sfd) { /* No partition table (SFD) */ + md = 0xF0; + } else { /* Create partition table (FDISK) */ + mem_set(fs->win, 0, SS(fs)); + tbl = fs->win+MBR_Table; /* Create partition table for single partition in the drive */ + tbl[1] = 1; /* Partition start head */ + tbl[2] = 1; /* Partition start sector */ + tbl[3] = 0; /* Partition start cylinder */ + tbl[4] = sys; /* System type */ + tbl[5] = 254; /* Partition end head */ + n = (b_vol + n_vol) / 63 / 255; + tbl[6] = (BYTE)((n >> 2) | 63); /* Partition end sector */ + tbl[7] = (BYTE)n; /* End cylinder */ + ST_DWORD(tbl+8, 63); /* Partition start in LBA */ + ST_DWORD(tbl+12, n_vol); /* Partition size in LBA */ + ST_WORD(fs->win+BS_55AA, 0xAA55); /* MBR signature */ + if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) /* Write it to the MBR sector */ + return FR_DISK_ERR; + md = 0xF8; + } } - /* Create volume boot record */ + /* Create BPB in the VBR */ tbl = fs->win; /* Clear sector */ mem_set(tbl, 0, SS(fs)); mem_cpy(tbl, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code, OEM name */ @@ -3699,10 +3787,10 @@ FRESULT f_mkfs ( mem_cpy(tbl+BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */ } ST_WORD(tbl+BS_55AA, 0xAA55); /* Signature (Offset is fixed here regardless of sector size) */ - if (disk_write(drv, tbl, b_vol, 1) != RES_OK) /* Write VBR */ + if (disk_write(pdrv, tbl, b_vol, 1) != RES_OK) /* Write it to the VBR sector */ return FR_DISK_ERR; if (fmt == FS_FAT32) /* Write backup VBR if needed (VBR+6) */ - disk_write(drv, tbl, b_vol + 6, 1); + disk_write(pdrv, tbl, b_vol + 6, 1); /* Initialize FAT area */ wsect = b_fat; @@ -3718,11 +3806,11 @@ FRESULT f_mkfs ( ST_DWORD(tbl+4, 0xFFFFFFFF); ST_DWORD(tbl+8, 0x0FFFFFFF); /* Reserve cluster #2 for root dir */ } - if (disk_write(drv, tbl, wsect++, 1) != RES_OK) + if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK) return FR_DISK_ERR; mem_set(tbl, 0, SS(fs)); /* Fill following FAT entries with zero */ for (n = 1; n < n_fat; n++) { /* This loop may take a time on FAT32 volume due to many single sector writes */ - if (disk_write(drv, tbl, wsect++, 1) != RES_OK) + if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK) return FR_DISK_ERR; } } @@ -3730,7 +3818,7 @@ FRESULT f_mkfs ( /* Initialize root directory */ i = (fmt == FS_FAT32) ? au : n_dir; do { - if (disk_write(drv, tbl, wsect++, 1) != RES_OK) + if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK) return FR_DISK_ERR; } while (--i); @@ -3739,7 +3827,7 @@ FRESULT f_mkfs ( DWORD eb[2]; eb[0] = wsect; eb[1] = wsect + (n_clst - ((fmt == FS_FAT32) ? 1 : 0)) * au - 1; - disk_ioctl(drv, CTRL_ERASE_SECTOR, eb); + disk_ioctl(pdrv, CTRL_ERASE_SECTOR, eb); } #endif @@ -3750,13 +3838,82 @@ FRESULT f_mkfs ( ST_DWORD(tbl+FSI_Free_Count, n_clst - 1); /* Number of free clusters */ ST_DWORD(tbl+FSI_Nxt_Free, 2); /* Last allocated cluster# */ ST_WORD(tbl+BS_55AA, 0xAA55); - disk_write(drv, tbl, b_vol + 1, 1); /* Write original (VBR+1) */ - disk_write(drv, tbl, b_vol + 7, 1); /* Write backup (VBR+7) */ + disk_write(pdrv, tbl, b_vol + 1, 1); /* Write original (VBR+1) */ + disk_write(pdrv, tbl, b_vol + 7, 1); /* Write backup (VBR+7) */ + } + + return (disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR; +} + + +#if _MULTI_PARTITION == 2 +/*-----------------------------------------------------------------------*/ +/* Divide Physical Drive */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_fdisk ( + BYTE pdrv, /* Physical drive number */ + const DWORD szt[], /* Pointer to the size table for each partitions */ + void* work /* Pointer to the working buffer */ +) +{ + UINT i, n, sz_cyl, tot_cyl, b_cyl, e_cyl, p_cyl; + BYTE s_hd, e_hd, *p, *buf = (BYTE*)work; + DSTATUS stat; + DWORD sz_disk, sz_part, s_part; + + + stat = disk_initialize(pdrv); + if (stat & STA_NOINIT) return FR_NOT_READY; + if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; + if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR; + + /* Determine CHS in the table regardless of the drive geometry */ + for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ; + if (n == 256) n--; + e_hd = n - 1; + sz_cyl = 63 * n; + tot_cyl = sz_disk / sz_cyl; + + /* Create partition table */ + mem_set(buf, 0, _MAX_SS); + p = buf + MBR_Table; b_cyl = 0; + for (i = 0; i < 4; i++, p += SZ_PTE) { + p_cyl = (szt[i] <= 100) ? (DWORD)tot_cyl * szt[i] / 100 : szt[i] / sz_cyl; + if (!p_cyl) continue; + s_part = (DWORD)sz_cyl * b_cyl; + sz_part = (DWORD)sz_cyl * p_cyl; + if (i == 0) { /* Exclude first track of cylinder 0 */ + s_hd = 1; + s_part += 63; sz_part -= 63; + } else { + s_hd = 0; + } + e_cyl = b_cyl + p_cyl - 1; + if (e_cyl >= tot_cyl) return FR_INVALID_PARAMETER; + + /* Set partition table */ + p[1] = s_hd; /* Start head */ + p[2] = (BYTE)((b_cyl >> 2) + 1); /* Start sector */ + p[3] = (BYTE)b_cyl; /* Start cylinder */ + p[4] = 0x06; /* System type (temporary setting) */ + p[5] = e_hd; /* End head */ + p[6] = (BYTE)((e_cyl >> 2) + 63); /* End sector */ + p[7] = (BYTE)e_cyl; /* End cylinder */ + ST_DWORD(p + 8, s_part); /* Start sector in LBA */ + ST_DWORD(p + 12, sz_part); /* Partition size */ + + /* Next partition */ + b_cyl += p_cyl; } + ST_WORD(p, 0xAA55); - return (disk_ioctl(drv, CTRL_SYNC, (void*)0) == RES_OK) ? FR_OK : FR_DISK_ERR; + /* Write it to the MBR */ + return (disk_write(pdrv, buf, 0, 1) || disk_ioctl(pdrv, CTRL_SYNC, 0)) ? FR_DISK_ERR : FR_OK; } + +#endif /* _MULTI_PARTITION == 2 */ #endif /* _USE_MKFS && !_FS_READONLY */ @@ -3894,7 +4051,7 @@ int f_printf ( UINT i, j, w; ULONG v; TCHAR c, d, s[16], *p; - int res, cc; + int res, chc, cc; va_start(arp, str); @@ -3930,11 +4087,13 @@ int f_printf ( case 'S' : /* String */ p = va_arg(arp, TCHAR*); for (j = 0; p[j]; j++) ; - res = 0; - while (!(f & 2) && j++ < w) res += (cc = f_putc(' ', fil)); - res += (cc = f_puts(p, fil)); - while (j++ < w) res += (cc = f_putc(' ', fil)); - if (cc != EOF) cc = res; + chc = 0; + if (!(f & 2)) { + while (j++ < w) chc += (cc = f_putc(' ', fil)); + } + chc += (cc = f_puts(p, fil)); + while (j++ < w) chc += (cc = f_putc(' ', fil)); + if (cc != EOF) cc = chc; continue; case 'C' : /* Character */ cc = f_putc((TCHAR)va_arg(arp, int), fil); continue; @@ -3945,14 +4104,14 @@ int f_printf ( case 'D' : /* Signed decimal */ case 'U' : /* Unsigned decimal */ r = 10; break; - case 'X' : /* Hexadecimal */ + case 'X' : /* Hexdecimal */ r = 16; break; default: /* Unknown type (pass-through) */ cc = f_putc(c, fil); continue; } /* Get an argument and put it in numeral */ - v = (f & 4) ? va_arg(arp, long) : ((d == 'D') ? (long)va_arg(arp, int) : va_arg(arp, unsigned int)); + v = (f & 4) ? (ULONG)va_arg(arp, long) : ((d == 'D') ? (ULONG)(long)va_arg(arp, int) : (ULONG)va_arg(arp, unsigned int)); if (d == 'D' && (v & 0x80000000)) { v = 0 - v; f |= 8; @@ -3962,7 +4121,7 @@ int f_printf ( d = (TCHAR)(v % r); v /= r; if (d > 9) d += (c == 'x') ? 0x27 : 0x07; s[i++] = d + '0'; - } while (v && i < sizeof(s) / sizeof(s[0])); + } while (v && i < sizeof s / sizeof s[0]); if (f & 8) s[i++] = '-'; j = i; d = (f & 1) ? '0' : ' '; res = 0; @@ -3978,4 +4137,3 @@ int f_printf ( #endif /* !_FS_READONLY */ #endif /* _USE_STRFUNC */ - diff --git a/Projects/TempDataLogger/Lib/FATFs/ff.h b/Projects/TempDataLogger/Lib/FATFs/ff.h index 9788a6518..627cbaabe 100644 --- a/Projects/TempDataLogger/Lib/FATFs/ff.h +++ b/Projects/TempDataLogger/Lib/FATFs/ff.h @@ -1,11 +1,11 @@ /*---------------------------------------------------------------------------/ -/ FatFs - FAT file system module include file R0.08b (C)ChaN, 2011 +/ FatFs - FAT file system module include file R0.09a (C)ChaN, 2012 /----------------------------------------------------------------------------/ / FatFs module is a generic FAT file system module for small embedded systems. / This is a free software that opened for education, research and commercial / developments under license policy of following terms. / -/ Copyright (C) 2011, ChaN, all right reserved. +/ Copyright (C) 2012, ChaN, all right reserved. / / * The FatFs module is a free software and there is NO WARRANTY. / * No restriction on use. You can use, modify and redistribute it for @@ -15,7 +15,7 @@ /----------------------------------------------------------------------------*/ #ifndef _FATFS -#define _FATFS 8237 /* Revision ID */ +#define _FATFS 4004 /* Revision ID */ #ifdef __cplusplus extern "C" { @@ -33,17 +33,17 @@ extern "C" { /* Definitions of volume management */ #if _MULTI_PARTITION /* Multiple partition configuration */ -#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive# */ -#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition# */ typedef struct { - BYTE pd; /* Physical drive# */ - BYTE pt; /* Partition # (0-3) */ + BYTE pd; /* Physical drive number */ + BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */ } PARTITION; -extern const PARTITION VolToPart[]; /* Volume - Physical location resolution table */ +extern PARTITION VolToPart[]; /* Volume - Partition resolution table */ +#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */ +#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */ -#else /* Single partition configuration */ -#define LD2PD(vol) (vol) /* Logical drive# is bound to the same physical drive# */ -#define LD2PT(vol) 0 /* Always mounts the 1st partition */ +#else /* Single partition configuration */ +#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */ +#define LD2PT(vol) 0 /* Always mounts the 1st partition or in SFD */ #endif @@ -84,7 +84,7 @@ typedef struct { WORD id; /* File system mount ID */ WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ #if _MAX_SS != 512 - WORD ssize; /* Bytes per sector (512,1024,2048,4096) */ + WORD ssize; /* Bytes per sector (512, 1024, 2048 or 4096) */ #endif #if _FS_REENTRANT _SYNC_t sobj; /* Identifier of sync object */ @@ -111,24 +111,24 @@ typedef struct { /* File object structure (FIL) */ typedef struct { - FATFS* fs; /* Pointer to the owner file system object */ - WORD id; /* Owner file system mount ID */ + FATFS* fs; /* Pointer to the related file system object */ + WORD id; /* File system mount ID of the related file system object */ BYTE flag; /* File status flags */ BYTE pad1; - DWORD fptr; /* File read/write pointer (0 on file open) */ + DWORD fptr; /* File read/write pointer (0ed on file open) */ DWORD fsize; /* File size */ - DWORD sclust; /* File start cluster (0 when fsize==0) */ - DWORD clust; /* Current cluster */ - DWORD dsect; /* Current data sector */ + DWORD sclust; /* File data start cluster (0:no data cluster, always 0 when fsize is 0) */ + DWORD clust; /* Current cluster of fpter */ + DWORD dsect; /* Current data sector of fpter */ #if !_FS_READONLY DWORD dir_sect; /* Sector containing the directory entry */ - BYTE* dir_ptr; /* Ponter to the directory entry in the window */ + BYTE* dir_ptr; /* Pointer to the directory entry in the window */ #endif #if _USE_FASTSEEK DWORD* cltbl; /* Pointer to the cluster link map table (null on file open) */ #endif -#if _FS_SHARE - UINT lockid; /* File lock ID (index of file semaphore table) */ +#if _FS_LOCK + UINT lockid; /* File lock ID (index of file semaphore table Files[]) */ #endif #if !_FS_TINY BYTE buf[_MAX_SS]; /* File data read/write buffer */ @@ -176,24 +176,25 @@ typedef struct { typedef enum { FR_OK = 0, /* (0) Succeeded */ - FR_DISK_ERR, /* (1) A hard error occured in the low level disk I/O layer */ + FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */ FR_INT_ERR, /* (2) Assertion failed */ FR_NOT_READY, /* (3) The physical drive cannot work */ FR_NO_FILE, /* (4) Could not find the file */ FR_NO_PATH, /* (5) Could not find the path */ FR_INVALID_NAME, /* (6) The path name format is invalid */ - FR_DENIED, /* (7) Acces denied due to prohibited access or directory full */ - FR_EXIST, /* (8) Acces denied due to prohibited access */ + FR_DENIED, /* (7) Access denied due to prohibited access or directory full */ + FR_EXIST, /* (8) Access denied due to prohibited access */ FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */ FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ FR_NOT_ENABLED, /* (12) The volume has no work area */ - FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume on the physical drive */ + FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */ FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ - FR_TOO_MANY_OPEN_FILES /* (18) Number of open files > _FS_SHARE */ + FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */ + FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ } FRESULT; @@ -216,27 +217,28 @@ FRESULT f_sync (FIL*); /* Flush cached data of a writing file */ FRESULT f_unlink (const TCHAR*); /* Delete an existing file or directory */ FRESULT f_mkdir (const TCHAR*); /* Create a new directory */ FRESULT f_chmod (const TCHAR*, BYTE, BYTE); /* Change attribute of the file/dir */ -FRESULT f_utime (const TCHAR*, const FILINFO*); /* Change time-stamp of the file/dir */ +FRESULT f_utime (const TCHAR*, const FILINFO*); /* Change times-tamp of the file/dir */ FRESULT f_rename (const TCHAR*, const TCHAR*); /* Rename/Move a file or directory */ -FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*); /* Forward data to the stream */ -FRESULT f_mkfs (BYTE, BYTE, UINT); /* Create a file system on the drive */ FRESULT f_chdrive (BYTE); /* Change current drive */ FRESULT f_chdir (const TCHAR*); /* Change current directory */ FRESULT f_getcwd (TCHAR*, UINT); /* Get current directory */ +FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*); /* Forward data to the stream */ +FRESULT f_mkfs (BYTE, BYTE, UINT); /* Create a file system on the drive */ +FRESULT f_fdisk (BYTE, const DWORD[], void*); /* Divide a physical drive into some partitions */ int f_putc (TCHAR, FIL*); /* Put a character to the file */ int f_puts (const TCHAR*, FIL*); /* Put a string to the file */ int f_printf (FIL*, const TCHAR*, ...); /* Put a formatted string to the file */ TCHAR* f_gets (TCHAR*, int, FIL*); /* Get a string from the file */ -#ifndef EOF -#define EOF (-1) -#endif - #define f_eof(fp) (((fp)->fptr == (fp)->fsize) ? 1 : 0) #define f_error(fp) (((fp)->flag & FA__ERROR) ? 1 : 0) #define f_tell(fp) ((fp)->fptr) #define f_size(fp) ((fp)->fsize) +#ifndef EOF +#define EOF (-1) +#endif + @@ -308,7 +310,7 @@ int ff_del_syncobj (_SYNC_t); /* Delete a sync object */ #define AM_MASK 0x3F /* Mask of defined bits */ -/* Fast seek function */ +/* Fast seek feature */ #define CREATE_LINKMAP 0xFFFFFFFF @@ -333,4 +335,3 @@ int ff_del_syncobj (_SYNC_t); /* Delete a sync object */ #endif #endif /* _FATFS */ - diff --git a/Projects/TempDataLogger/Lib/FATFs/ffconf.h b/Projects/TempDataLogger/Lib/FATFs/ffconf.h index 42528bbc3..63a4e7823 100644 --- a/Projects/TempDataLogger/Lib/FATFs/ffconf.h +++ b/Projects/TempDataLogger/Lib/FATFs/ffconf.h @@ -1,5 +1,5 @@ /*---------------------------------------------------------------------------/ -/ FatFs - FAT file system module configuration file R0.08b (C)ChaN, 2011 +/ FatFs - FAT file system module configuration file R0.09a (C)ChaN, 2012 /----------------------------------------------------------------------------/ / / CAUTION! Do not forget to make clean the project after any changes to @@ -7,7 +7,7 @@ / /----------------------------------------------------------------------------*/ #ifndef _FFCONF -#define _FFCONF 8237 /* Revision ID */ +#define _FFCONF 4004 /* Revision ID */ /*---------------------------------------------------------------------------/ @@ -36,7 +36,7 @@ / 3: f_lseek is removed in addition to 2. */ -#define _USE_STRFUNC 0 /* 0:Disable or 1/2:Enable */ +#define _USE_STRFUNC 0 /* 0:Disable or 1-2:Enable */ /* To enable string functions, set _USE_STRFUNC to 1 or 2. */ @@ -137,7 +137,7 @@ / and GET_SECTOR_SIZE command must be implememted to the disk_ioctl function. */ -#define _MULTI_PARTITION 0 /* 0:Single partition or 1:Multiple partition */ +#define _MULTI_PARTITION 0 /* 0:Single partition, 1/2:Enable multiple partition */ /* When set to 0, each volume is bound to the same physical drive number and / it can mount only first primaly partition. When it is set to 1, each volume / is tied to the partitions listed in VolToPart[]. */ @@ -163,7 +163,8 @@ / When the byte order on the memory is big-endian or address miss-aligned word / access results incorrect behavior, the _WORD_ACCESS must be set to 0. / If it is not the case, the value can also be set to 1 to improve the -/ performance and code size. */ +/ performance and code size. +*/ /* A header file that defines sync object types on the O/S, such as @@ -181,9 +182,9 @@ / function must be added to the project. */ -#define _FS_SHARE 0 /* 0:Disable or >=1:Enable */ -/* To enable file shareing feature, set _FS_SHARE to 1 or greater. The value - defines how many files can be opened simultaneously. */ +#define _FS_LOCK 0 /* 0:Disable or >=1:Enable */ +/* To enable file lock control feature, set _FS_LOCK to 1 or greater. + The value defines how many files can be opened simultaneously. */ #endif /* _FFCONFIG */ diff --git a/Projects/Webserver/Lib/FATFs/00readme.txt b/Projects/Webserver/Lib/FATFs/00readme.txt index c78da3186..80d8843d1 100644 --- a/Projects/Webserver/Lib/FATFs/00readme.txt +++ b/Projects/Webserver/Lib/FATFs/00readme.txt @@ -1,4 +1,4 @@ -FatFs Module Source Files R0.08b (C)ChaN, 2011 +FatFs Module Source Files R0.09a (C)ChaN, 2012 FILES @@ -7,7 +7,8 @@ FILES ff.h Common include file for FatFs and application module. ff.c FatFs module. diskio.h Common include file for FatFs and disk I/O module. - integer.h Alternative type definitions for integer variables. + diskio.c An example of glue function to attach existing disk I/O module to FatFs. + integer.h Integer type definitions for FatFs. option Optional external functions. Low level disk I/O module is not included in this archive because the FatFs @@ -23,7 +24,7 @@ AGREEMENTS small embedded systems. This is a free software and is opened for education, research and commercial developments under license policy of following trems. - Copyright (C) 2011, ChaN, all right reserved. + Copyright (C) 2012, ChaN, all right reserved. * The FatFs module is a free software and there is NO WARRANTY. * No restriction on use. You can use, modify and redistribute it for @@ -125,3 +126,10 @@ REVISION HISTORY f_lseek() reports required table size on creating CLMP. Extended format syntax of f_printf function. Ignores duplicated directory separators in given path names. + + Sep 06,'11 R0.09 f_mkfs() supports multiple partition to finish the multiple partition feature. + Added f_fdisk(). (_MULTI_PARTITION = 2) + + Aug 27,'12 R0.09a Fixed assertion failure due to OS/2 EA on FAT12/16. + Changed API rejects null object pointer to avoid crash. + Changed option name _FS_SHARE to _FS_LOCK. diff --git a/Projects/Webserver/Lib/FATFs/diskio.c b/Projects/Webserver/Lib/FATFs/diskio.c index 64daad9cd..b119b1a40 100644 --- a/Projects/Webserver/Lib/FATFs/diskio.c +++ b/Projects/Webserver/Lib/FATFs/diskio.c @@ -38,7 +38,7 @@ DRESULT disk_read ( BYTE drv, /* Physical drive number (0..) */ BYTE *buff, /* Data buffer to store read data */ DWORD sector, /* Sector address (LBA) */ - BYTE count /* Number of sectors to read (1..255) */ + BYTE count /* Number of sectors to read (1..128) */ ) { DataflashManager_ReadBlocks_RAM(sector, count, buff); @@ -55,7 +55,7 @@ DRESULT disk_write ( BYTE drv, /* Physical drive number (0..) */ const BYTE *buff, /* Data to be written */ DWORD sector, /* Sector address (LBA) */ - BYTE count /* Number of sectors to write (1..255) */ + BYTE count /* Number of sectors to write (1..128) */ ) { DataflashManager_WriteBlocks_RAM(sector, count, buff); diff --git a/Projects/Webserver/Lib/FATFs/diskio.h b/Projects/Webserver/Lib/FATFs/diskio.h index 0d3454366..65e3048a0 100644 --- a/Projects/Webserver/Lib/FATFs/diskio.h +++ b/Projects/Webserver/Lib/FATFs/diskio.h @@ -2,10 +2,12 @@ / Low level disk interface module include file /-----------------------------------------------------------------------*/ -#ifndef _DISKIO +#ifndef _DISKIO_DEFINED +#define _DISKIO_DEFINED -#define _READONLY 0 /* 1: Read-only mode */ -#define _USE_IOCTL 0 +#ifdef __cplusplus +extern "C" { +#endif #include "integer.h" #include "ff.h" @@ -32,9 +34,7 @@ typedef enum { DSTATUS disk_initialize (BYTE); DSTATUS disk_status (BYTE); DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE); -#if _READONLY == 0 DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE); -#endif DRESULT disk_ioctl (BYTE, BYTE, void*); @@ -45,6 +45,8 @@ DRESULT disk_ioctl (BYTE, BYTE, void*); #define STA_PROTECT 0x04 /* Write protected */ -#define _DISKIO +#ifdef __cplusplus +} #endif +#endif diff --git a/Projects/Webserver/Lib/FATFs/ff.c b/Projects/Webserver/Lib/FATFs/ff.c index cd1dda9be..2f58adf83 100644 --- a/Projects/Webserver/Lib/FATFs/ff.c +++ b/Projects/Webserver/Lib/FATFs/ff.c @@ -1,11 +1,11 @@ /*----------------------------------------------------------------------------/ -/ FatFs - FAT file system module R0.08b (C)ChaN, 2011 +/ FatFs - FAT file system module R0.09a (C)ChaN, 2012 /-----------------------------------------------------------------------------/ / FatFs module is a generic FAT file system module for small embedded systems. / This is a free software that opened for education, research and commercial / developments under license policy of following terms. / -/ Copyright (C) 2011, ChaN, all right reserved. +/ Copyright (C) 2012, ChaN, all right reserved. / / * The FatFs module is a free software and there is NO WARRANTY. / * No restriction on use. You can use, modify and redistribute it for @@ -86,7 +86,13 @@ / Jan 15,'11 R0.08b Fast seek feature is also applied to f_read() and f_write(). / f_lseek() reports required table size on creating CLMP. / Extended format syntax of f_printf function. -/ Ignores duplicated directory separators in given path names. +/ Ignores duplicated directory separators in given path name. +/ +/ Sep 06,'11 R0.09 f_mkfs() supports multiple partition to finish the multiple partition feature. +/ Added f_fdisk(). (_MULTI_PARTITION = 2) +/ Aug 27,'12 R0.09a Fixed assertion failure due to OS/2 EA on FAT12/16 volume. +/ Changed f_open() and f_opendir reject null object pointer to avoid crash. +/ Changed option name _FS_SHARE to _FS_LOCK. /---------------------------------------------------------------------------*/ #include "ff.h" /* FatFs configurations and declarations */ @@ -99,7 +105,7 @@ ---------------------------------------------------------------------------*/ -#if _FATFS != 8237 +#if _FATFS != 4004 /* Revision ID */ #error Wrong include file (ff.h). #endif @@ -109,7 +115,7 @@ #error Wrong sector size. #endif #if _MAX_SS != 512 -#define SS(fs) ((fs)->ssize) /* Multiple sector size */ +#define SS(fs) ((fs)->ssize) /* Variable sector size */ #else #define SS(fs) 512U /* Fixed sector size */ #endif @@ -130,10 +136,10 @@ #define ABORT(fs, res) { fp->flag |= FA__ERROR; LEAVE_FF(fs, res); } -/* File sharing feature */ -#if _FS_SHARE +/* File access control feature */ +#if _FS_LOCK #if _FS_READONLY -#error _FS_SHARE must be 0 on read-only cfg. +#error _FS_LOCK must be 0 on read-only cfg. #endif typedef struct { FATFS *fs; /* File ID 1, volume (NULL:blank entry) */ @@ -144,10 +150,6 @@ typedef struct { #endif -/* Misc definitions */ -#define LD_CLUST(dir) (((DWORD)LD_WORD(dir+DIR_FstClusHI)<<16) | LD_WORD(dir+DIR_FstClusLO)) -#define ST_CLUST(dir,cl) {ST_WORD(dir+DIR_FstClusLO, cl); ST_WORD(dir+DIR_FstClusHI, (DWORD)cl>>16);} - /* DBCS code ranges and SBCS extend char conversion table */ @@ -434,8 +436,10 @@ typedef struct { #define DIR_Name 0 /* Short file name (11) */ #define DIR_Attr 11 /* Attribute (1) */ #define DIR_NTres 12 /* NT flag (1) */ +#define DIR_CrtTimeTenth 13 /* Created time sub-second (1) */ #define DIR_CrtTime 14 /* Created time (2) */ #define DIR_CrtDate 16 /* Created date (2) */ +#define DIR_LstAccDate 18 /* Last accessed date (2) */ #define DIR_FstClusHI 20 /* Higher 16-bit of first cluster (2) */ #define DIR_WrtTime 22 /* Modified time (2) */ #define DIR_WrtDate 24 /* Modified date (2) */ @@ -449,17 +453,22 @@ typedef struct { #define SZ_DIR 32 /* Size of a directory entry */ #define LLE 0x40 /* Last long entry flag in LDIR_Ord */ #define DDE 0xE5 /* Deleted directory entry mark in DIR_Name[0] */ -#define NDDE 0x05 /* Replacement of a character collides with DDE */ +#define NDDE 0x05 /* Replacement of the character collides with DDE */ /*------------------------------------------------------------*/ -/* Work area */ +/* Module private work area */ +/*------------------------------------------------------------*/ +/* Note that uninitialized variables with static duration are +/ zeroed/nulled at start-up. If not, the compiler or start-up +/ routine is out of ANSI-C standard. +*/ #if _VOLUMES static FATFS *FatFs[_VOLUMES]; /* Pointer to the file system objects (logical drives) */ #else -#error Number of drives must not be 0. +#error Number of volumes must not be 0. #endif static @@ -470,28 +479,28 @@ static BYTE CurrVol; /* Current drive */ #endif -#if _FS_SHARE +#if _FS_LOCK static -FILESEM Files[_FS_SHARE]; /* File lock semaphores */ +FILESEM Files[_FS_LOCK]; /* File lock semaphores */ #endif -#if _USE_LFN == 0 /* No LFN */ +#if _USE_LFN == 0 /* No LFN feature */ #define DEF_NAMEBUF BYTE sfn[12] #define INIT_BUF(dobj) (dobj).fn = sfn #define FREE_BUF() -#elif _USE_LFN == 1 /* LFN with static LFN working buffer */ +#elif _USE_LFN == 1 /* LFN feature with static working buffer */ static WCHAR LfnBuf[_MAX_LFN+1]; #define DEF_NAMEBUF BYTE sfn[12] #define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = LfnBuf; } #define FREE_BUF() -#elif _USE_LFN == 2 /* LFN with dynamic LFN working buffer on the stack */ +#elif _USE_LFN == 2 /* LFN feature with dynamic working buffer on the stack */ #define DEF_NAMEBUF BYTE sfn[12]; WCHAR lbuf[_MAX_LFN+1] #define INIT_BUF(dobj) { (dobj).fn = sfn; (dobj).lfn = lbuf; } #define FREE_BUF() -#elif _USE_LFN == 3 /* LFN with dynamic LFN working buffer on the heap */ +#elif _USE_LFN == 3 /* LFN feature with dynamic working buffer on the heap */ #define DEF_NAMEBUF BYTE sfn[12]; WCHAR *lfn #define INIT_BUF(dobj) { lfn = ff_memalloc((_MAX_LFN + 1) * 2); \ if (!lfn) LEAVE_FF((dobj).fs, FR_NOT_ENOUGH_CORE); \ @@ -523,10 +532,10 @@ void mem_cpy (void* dst, const void* src, UINT cnt) { const BYTE *s = (const BYTE*)src; #if _WORD_ACCESS == 1 - while (cnt >= sizeof(int)) { + while (cnt >= sizeof (int)) { *(int*)d = *(int*)s; - d += sizeof(int); s += sizeof(int); - cnt -= sizeof(int); + d += sizeof (int); s += sizeof (int); + cnt -= sizeof (int); } #endif while (cnt--) @@ -581,7 +590,8 @@ void unlock_fs ( FRESULT res /* Result code to be returned */ ) { - if (res != FR_NOT_ENABLED && + if (fs && + res != FR_NOT_ENABLED && res != FR_INVALID_DRIVE && res != FR_INVALID_OBJECT && res != FR_TIMEOUT) { @@ -593,9 +603,9 @@ void unlock_fs ( /*-----------------------------------------------------------------------*/ -/* File sharing control functions */ +/* File lock control functions */ /*-----------------------------------------------------------------------*/ -#if _FS_SHARE +#if _FS_LOCK static FRESULT chk_lock ( /* Check if the file can be accessed */ @@ -606,7 +616,7 @@ FRESULT chk_lock ( /* Check if the file can be accessed */ UINT i, be; /* Search file semaphore table */ - for (i = be = 0; i < _FS_SHARE; i++) { + for (i = be = 0; i < _FS_LOCK; i++) { if (Files[i].fs) { /* Existing entry */ if (Files[i].fs == dj->fs && /* Check if the file matched with an open file */ Files[i].clu == dj->sclust && @@ -615,7 +625,7 @@ FRESULT chk_lock ( /* Check if the file can be accessed */ be++; } } - if (i == _FS_SHARE) /* The file is not opened */ + if (i == _FS_LOCK) /* The file is not opened */ return (be || acc == 2) ? FR_OK : FR_TOO_MANY_OPEN_FILES; /* Is there a blank entry for new file? */ /* The file has been opened. Reject any open against writing file and all write mode open */ @@ -624,14 +634,12 @@ FRESULT chk_lock ( /* Check if the file can be accessed */ static -int enq_lock ( /* Check if an entry is available for a new file */ - FATFS* fs /* File system object */ -) +int enq_lock (void) /* Check if an entry is available for a new file */ { UINT i; - for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ; - return (i == _FS_SHARE) ? 0 : 1; + for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ; + return (i == _FS_LOCK) ? 0 : 1; } @@ -644,15 +652,15 @@ UINT inc_lock ( /* Increment file open counter and returns its index (0:int erro UINT i; - for (i = 0; i < _FS_SHARE; i++) { /* Find the file */ + for (i = 0; i < _FS_LOCK; i++) { /* Find the file */ if (Files[i].fs == dj->fs && Files[i].clu == dj->sclust && Files[i].idx == dj->index) break; } - if (i == _FS_SHARE) { /* Not opened. Register it as new. */ - for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ; - if (i == _FS_SHARE) return 0; /* No space to register (int err) */ + if (i == _FS_LOCK) { /* Not opened. Register it as new. */ + for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ; + if (i == _FS_LOCK) return 0; /* No space to register (int err) */ Files[i].fs = dj->fs; Files[i].clu = dj->sclust; Files[i].idx = dj->index; @@ -676,7 +684,7 @@ FRESULT dec_lock ( /* Decrement file open counter */ FRESULT res; - if (--i < _FS_SHARE) { + if (--i < _FS_LOCK) { n = Files[i].ctr; if (n == 0x100) n = 0; if (n) n--; @@ -697,7 +705,7 @@ void clear_lock ( /* Clear lock entries of the volume */ { UINT i; - for (i = 0; i < _FS_SHARE; i++) { + for (i = 0; i < _FS_LOCK; i++) { if (Files[i].fs == fs) Files[i].fs = 0; } } @@ -776,7 +784,7 @@ FRESULT sync ( /* FR_OK: successful, FR_DISK_ERR: failed */ fs->fsi_flag = 0; } /* Make sure that no pending write process in the physical drive */ - if (disk_ioctl(fs->drv, CTRL_SYNC, (void*)0) != RES_OK) + if (disk_ioctl(fs->drv, CTRL_SYNC, 0) != RES_OK) res = FR_DISK_ERR; } @@ -870,7 +878,7 @@ FRESULT put_fat ( } else { switch (fs->fs_type) { case FS_FAT12 : - bc = clst; bc += bc / 2; + bc = (UINT)clst; bc += bc / 2; res = move_window(fs, fs->fatbase + (bc / SS(fs))); if (res != FR_OK) break; p = &fs->win[bc % SS(fs)]; @@ -924,7 +932,7 @@ FRESULT remove_chain ( FRESULT res; DWORD nxt; #if _USE_ERASE - DWORD scl = clst, ecl = clst, resion[2]; + DWORD scl = clst, ecl = clst, rt[2]; #endif if (clst < 2 || clst >= fs->n_fatent) { /* Check range */ @@ -944,12 +952,12 @@ FRESULT remove_chain ( fs->fsi_flag = 1; } #if _USE_ERASE - if (ecl + 1 == nxt) { /* Next cluster is contiguous */ + if (ecl + 1 == nxt) { /* Is next cluster contiguous? */ ecl = nxt; - } else { /* End of contiguous clusters */ - resion[0] = clust2sect(fs, scl); /* Start sector */ - resion[1] = clust2sect(fs, ecl) + fs->csize - 1; /* End sector */ - disk_ioctl(fs->drv, CTRL_ERASE_SECTOR, resion); /* Erase the block */ + } else { /* End of contiguous clusters */ + rt[0] = clust2sect(fs, scl); /* Start sector */ + rt[1] = clust2sect(fs, ecl) + fs->csize - 1; /* End sector */ + disk_ioctl(fs->drv, CTRL_ERASE_SECTOR, rt); /* Erase the block */ scl = ecl = nxt; } #endif @@ -1040,7 +1048,7 @@ DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */ tbl = fp->cltbl + 1; /* Top of CLMT */ cl = ofs / SS(fp->fs) / fp->fs->csize; /* Cluster order from top of the file */ for (;;) { - ncl = *tbl++; /* Number of clusters in the fragment */ + ncl = *tbl++; /* Number of cluters in the fragment */ if (!ncl) return 0; /* End of table? (error) */ if (cl < ncl) break; /* In this fragment? */ cl -= ncl; tbl++; /* Next fragment */ @@ -1058,7 +1066,7 @@ DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */ static FRESULT dir_sdi ( DIR *dj, /* Pointer to directory object */ - WORD idx /* Directory index number */ + WORD idx /* Index of directory table */ ) { DWORD clst; @@ -1100,7 +1108,7 @@ FRESULT dir_sdi ( /*-----------------------------------------------------------------------*/ -/* Directory handling - Move directory index next */ +/* Directory handling - Move directory table index next */ /*-----------------------------------------------------------------------*/ static @@ -1113,6 +1121,7 @@ FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT an WORD i; + stretch = stretch; /* To suppress warning on read-only cfg. */ i = dj->index + 1; if (!i || !dj->sect) /* Report EOT when index has reached 65535 */ return FR_NO_FILE; @@ -1166,6 +1175,40 @@ FRESULT dir_next ( /* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT an +/*-----------------------------------------------------------------------*/ +/* Directory handling - Load/Store start cluster number */ +/*-----------------------------------------------------------------------*/ + +static +DWORD ld_clust ( + FATFS *fs, /* Pointer to the fs object */ + BYTE *dir /* Pointer to the directory entry */ +) +{ + DWORD cl; + + cl = LD_WORD(dir+DIR_FstClusLO); + if (fs->fs_type == FS_FAT32) + cl |= (DWORD)LD_WORD(dir+DIR_FstClusHI) << 16; + + return cl; +} + + +#if !_FS_READONLY +static +void st_clust ( + BYTE *dir, /* Pointer to the directory entry */ + DWORD cl /* Value to be set */ +) +{ + ST_WORD(dir+DIR_FstClusLO, cl); + ST_WORD(dir+DIR_FstClusHI, cl >> 16); +} +#endif + + + /*-----------------------------------------------------------------------*/ /* LFN handling - Test/Pick/Fit an LFN segment from/to directory entry */ /*-----------------------------------------------------------------------*/ @@ -1777,7 +1820,7 @@ FRESULT create_name ( if (c >= 0x80) { /* Extended char? */ b |= 3; /* Eliminate NT flag */ #ifdef _EXCVT - c = excvt[c-0x80]; /* Upper conversion (SBCS) */ + c = excvt[c - 0x80]; /* Upper conversion (SBCS) */ #else #if !_DF1S /* ASCII only cfg */ return FR_INVALID_NAME; @@ -1933,7 +1976,6 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ if ((UINT)*path < ' ') { /* Nul path means the start directory itself */ res = dir_sdi(dj, 0); dj->dir = 0; - } else { /* Follow path */ for (;;) { res = create_name(dj, &path); /* Get a segment */ @@ -1957,7 +1999,7 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ if (!(dir[DIR_Attr] & AM_DIR)) { /* Cannot follow because it is a file */ res = FR_NO_PATH; break; } - dj->sclust = LD_CLUST(dir); + dj->sclust = ld_clust(dj->fs, dir); } } @@ -1968,11 +2010,11 @@ FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */ /*-----------------------------------------------------------------------*/ -/* Load boot record and check if it is an FAT boot record */ +/* Load a sector and check if it is an FAT Volume Boot Record */ /*-----------------------------------------------------------------------*/ static -BYTE check_fs ( /* 0:The FAT BR, 1:Valid BR but not an FAT, 2:Not a BR, 3:Disk error */ +BYTE check_fs ( /* 0:FAT-VBR, 1:Any BR but not FAT, 2:Not a BR, 3:Disk error */ FATFS *fs, /* File system object */ DWORD sect /* Sector# (lba) to check if it is an FAT boot record or not */ ) @@ -2001,10 +2043,10 @@ static FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */ const TCHAR **path, /* Pointer to pointer to the path name (drive number) */ FATFS **rfs, /* Pointer to pointer to the found file system object */ - BYTE chk_wp /* !=0: Check media write protection for write access */ + BYTE wmode /* !=0: Check write protection for write access */ ) { - BYTE fmt, b, *tbl; + BYTE fmt, b, pi, *tbl; UINT vol; DSTATUS stat; DWORD bsect, fasize, tsect, sysect, nclst, szbfat; @@ -2012,6 +2054,7 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */ const TCHAR *p = *path; FATFS *fs; + /* Get logical drive number from the path name */ vol = p[0] - '0'; /* Is there a drive number? */ if (vol <= 9 && p[1] == ':') { /* Found a drive number, get and strip it */ @@ -2024,55 +2067,56 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */ #endif } - /* Check if the logical drive is valid or not */ + /* Check if the file system object is valid or not */ + *rfs = 0; if (vol >= _VOLUMES) /* Is the drive number valid? */ return FR_INVALID_DRIVE; - *rfs = fs = FatFs[vol]; /* Return pointer to the corresponding file system object */ + fs = FatFs[vol]; /* Get corresponding file system object */ if (!fs) return FR_NOT_ENABLED; /* Is the file system object available? */ ENTER_FF(fs); /* Lock file system */ - if (fs->fs_type) { /* If the logical drive has been mounted */ + *rfs = fs; /* Return pointer to the corresponding file system object */ + if (fs->fs_type) { /* If the volume has been mounted */ stat = disk_status(fs->drv); if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized (has not been changed), */ -#if !_FS_READONLY - if (chk_wp && (stat & STA_PROTECT)) /* Check write protection if needed */ + if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) /* Check write protection if needed */ return FR_WRITE_PROTECTED; -#endif return FR_OK; /* The file system object is valid */ } } - /* The logical drive must be mounted. */ - /* Following code attempts to mount a volume. (analyze BPB and initialize the fs object) */ + /* The file system object is not valid. */ + /* Following code attempts to mount the volume. (analyze BPB and initialize the fs object) */ fs->fs_type = 0; /* Clear the file system object */ - fs->drv = (BYTE)LD2PD(vol); /* Bind the logical drive and a physical drive */ - stat = disk_initialize(fs->drv); /* Initialize low level disk I/O layer */ + fs->drv = LD2PD(vol); /* Bind the logical drive and a physical drive */ + stat = disk_initialize(fs->drv); /* Initialize the physical drive */ if (stat & STA_NOINIT) /* Check if the initialization succeeded */ - return FR_NOT_READY; /* Failed to initialize due to no media or hard error */ + return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */ + if (!_FS_READONLY && wmode && (stat & STA_PROTECT)) /* Check disk write protection if needed */ + return FR_WRITE_PROTECTED; #if _MAX_SS != 512 /* Get disk sector size (variable sector size cfg only) */ if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &fs->ssize) != RES_OK) return FR_DISK_ERR; #endif -#if !_FS_READONLY - if (chk_wp && (stat & STA_PROTECT)) /* Check disk write protection if needed */ - return FR_WRITE_PROTECTED; -#endif - /* Search FAT partition on the drive. Supports only generic partitioning, FDISK and SFD. */ - fmt = check_fs(fs, bsect = 0); /* Check sector 0 if it is a VBR */ - if (fmt == 1) { /* Not an FAT-VBR, the disk may be partitioned */ - /* Check the partition listed in top of the partition table */ - tbl = &fs->win[MBR_Table + LD2PT(vol) * SZ_PTE];/* Partition table */ - if (tbl[4]) { /* Is the partition existing? */ - bsect = LD_DWORD(&tbl[8]); /* Partition offset in LBA */ - fmt = check_fs(fs, bsect); /* Check the partition */ + /* Search FAT partition on the drive. Supports only generic partitions, FDISK and SFD. */ + fmt = check_fs(fs, bsect = 0); /* Load sector 0 and check if it is an FAT-VBR (in SFD) */ + if (LD2PT(vol) && !fmt) fmt = 1; /* Force non-SFD if the volume is forced partition */ + if (fmt == 1) { /* Not an FAT-VBR, the physical drive can be partitioned */ + /* Check the partition listed in the partition table */ + pi = LD2PT(vol); + if (pi) pi--; + tbl = &fs->win[MBR_Table + pi * SZ_PTE];/* Partition table */ + if (tbl[4]) { /* Is the partition existing? */ + bsect = LD_DWORD(&tbl[8]); /* Partition offset in LBA */ + fmt = check_fs(fs, bsect); /* Check the partition */ } } if (fmt == 3) return FR_DISK_ERR; - if (fmt) return FR_NO_FILESYSTEM; /* No FAT volume is found */ + if (fmt) return FR_NO_FILESYSTEM; /* No FAT volume is found */ - /* Following code initializes the file system object */ + /* An FAT volume is found. Following code initializes the file system object */ if (LD_WORD(fs->win+BPB_BytsPerSec) != SS(fs)) /* (BPB_BytsPerSec must be equal to the physical sector size) */ return FR_NO_FILESYSTEM; @@ -2148,7 +2192,7 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */ #if _FS_RPATH fs->cdir = 0; /* Current directory (root dir) */ #endif -#if _FS_SHARE /* Clear file lock semaphores */ +#if _FS_LOCK /* Clear file lock semaphores */ clear_lock(fs); #endif @@ -2164,16 +2208,19 @@ FRESULT chk_mounted ( /* FR_OK(0): successful, !=0: any error occurred */ static FRESULT validate ( /* FR_OK(0): The object is valid, !=0: Invalid */ - FATFS *fs, /* Pointer to the file system object */ - WORD id /* Member id of the target object to be checked */ + void* obj /* Pointer to the object FIL/DIR to check validity */ ) { - if (!fs || !fs->fs_type || fs->id != id) + FIL *fil; + + + fil = (FIL*)obj; /* Assuming offset of fs and id in the FIL/DIR is identical */ + if (!fil->fs || !fil->fs->fs_type || fil->fs->id != fil->id) return FR_INVALID_OBJECT; - ENTER_FF(fs); /* Lock file system */ + ENTER_FF(fil->fs); /* Lock file system */ - if (disk_status(fs->drv) & STA_NOINIT) + if (disk_status(fil->fs->drv) & STA_NOINIT) return FR_NOT_READY; return FR_OK; @@ -2202,27 +2249,27 @@ FRESULT f_mount ( FATFS *rfs; - if (vol >= _VOLUMES) /* Check if the drive number is valid */ + if (vol >= _VOLUMES) /* Check if the drive number is valid */ return FR_INVALID_DRIVE; - rfs = FatFs[vol]; /* Get current fs object */ + rfs = FatFs[vol]; /* Get current fs object */ if (rfs) { -#if _FS_SHARE +#if _FS_LOCK clear_lock(rfs); #endif -#if _FS_REENTRANT /* Discard sync object of the current volume */ +#if _FS_REENTRANT /* Discard sync object of the current volume */ if (!ff_del_syncobj(rfs->sobj)) return FR_INT_ERR; #endif - rfs->fs_type = 0; /* Clear old fs object */ + rfs->fs_type = 0; /* Clear old fs object */ } if (fs) { - fs->fs_type = 0; /* Clear new fs object */ -#if _FS_REENTRANT /* Create sync object for the new volume */ + fs->fs_type = 0; /* Clear new fs object */ +#if _FS_REENTRANT /* Create sync object for the new volume */ if (!ff_cre_syncobj(vol, &fs->sobj)) return FR_INT_ERR; #endif } - FatFs[vol] = fs; /* Register new fs object */ + FatFs[vol] = fs; /* Register new fs object */ return FR_OK; } @@ -2246,6 +2293,7 @@ FRESULT f_open ( DEF_NAMEBUF; + if (!fp) return FR_INVALID_OBJECT; fp->fs = 0; /* Clear file object */ #if !_FS_READONLY @@ -2255,103 +2303,104 @@ FRESULT f_open ( mode &= FA_READ; res = chk_mounted(&path, &dj.fs, 0); #endif - INIT_BUF(dj); - if (res == FR_OK) + if (res == FR_OK) { + INIT_BUF(dj); res = follow_path(&dj, path); /* Follow the file path */ - dir = dj.dir; - + dir = dj.dir; #if !_FS_READONLY /* R/W configuration */ - if (res == FR_OK) { - if (!dir) /* Current dir itself */ - res = FR_INVALID_NAME; -#if _FS_SHARE - else - res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0); + if (res == FR_OK) { + if (!dir) /* Current dir itself */ + res = FR_INVALID_NAME; +#if _FS_LOCK + else + res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0); #endif - } - /* Create or Open a file */ - if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) { - DWORD dw, cl; - - if (res != FR_OK) { /* No file, create new */ - if (res == FR_NO_FILE) /* There is no file to open, create a new entry */ -#if _FS_SHARE - res = enq_lock(dj.fs) ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES; + } + /* Create or Open a file */ + if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) { + DWORD dw, cl; + + if (res != FR_OK) { /* No file, create new */ + if (res == FR_NO_FILE) /* There is no file to open, create a new entry */ +#if _FS_LOCK + res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES; #else - res = dir_register(&dj); + res = dir_register(&dj); #endif - mode |= FA_CREATE_ALWAYS; /* File is created */ - dir = dj.dir; /* New entry */ - } - else { /* Any object is already existing */ - if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) { /* Cannot overwrite it (R/O or DIR) */ - res = FR_DENIED; - } else { - if (mode & FA_CREATE_NEW) /* Cannot create as new file */ - res = FR_EXIST; + mode |= FA_CREATE_ALWAYS; /* File is created */ + dir = dj.dir; /* New entry */ } - } - if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate it if overwrite mode */ - dw = get_fattime(); /* Created time */ - ST_DWORD(dir+DIR_CrtTime, dw); - dir[DIR_Attr] = 0; /* Reset attribute */ - ST_DWORD(dir+DIR_FileSize, 0); /* size = 0 */ - cl = LD_CLUST(dir); /* Get start cluster */ - ST_CLUST(dir, 0); /* cluster = 0 */ - dj.fs->wflag = 1; - if (cl) { /* Remove the cluster chain if exist */ - dw = dj.fs->winsect; - res = remove_chain(dj.fs, cl); - if (res == FR_OK) { - dj.fs->last_clust = cl - 1; /* Reuse the cluster hole */ - res = move_window(dj.fs, dw); + else { /* Any object is already existing */ + if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) { /* Cannot overwrite it (R/O or DIR) */ + res = FR_DENIED; + } else { + if (mode & FA_CREATE_NEW) /* Cannot create as new file */ + res = FR_EXIST; + } + } + if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) { /* Truncate it if overwrite mode */ + dw = get_fattime(); /* Created time */ + ST_DWORD(dir+DIR_CrtTime, dw); + dir[DIR_Attr] = 0; /* Reset attribute */ + ST_DWORD(dir+DIR_FileSize, 0); /* size = 0 */ + cl = ld_clust(dj.fs, dir); /* Get start cluster */ + st_clust(dir, 0); /* cluster = 0 */ + dj.fs->wflag = 1; + if (cl) { /* Remove the cluster chain if exist */ + dw = dj.fs->winsect; + res = remove_chain(dj.fs, cl); + if (res == FR_OK) { + dj.fs->last_clust = cl - 1; /* Reuse the cluster hole */ + res = move_window(dj.fs, dw); + } } } } - } - else { /* Open an existing file */ - if (res == FR_OK) { /* Follow succeeded */ - if (dir[DIR_Attr] & AM_DIR) { /* It is a directory */ - res = FR_NO_FILE; - } else { - if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */ - res = FR_DENIED; + else { /* Open an existing file */ + if (res == FR_OK) { /* Follow succeeded */ + if (dir[DIR_Attr] & AM_DIR) { /* It is a directory */ + res = FR_NO_FILE; + } else { + if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */ + res = FR_DENIED; + } } } - } - if (res == FR_OK) { - if (mode & FA_CREATE_ALWAYS) /* Set file change flag if created or overwritten */ - mode |= FA__WRITTEN; - fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */ - fp->dir_ptr = dir; -#if _FS_SHARE - fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0); - if (!fp->lockid) res = FR_INT_ERR; + if (res == FR_OK) { + if (mode & FA_CREATE_ALWAYS) /* Set file change flag if created or overwritten */ + mode |= FA__WRITTEN; + fp->dir_sect = dj.fs->winsect; /* Pointer to the directory entry */ + fp->dir_ptr = dir; +#if _FS_LOCK + fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0); + if (!fp->lockid) res = FR_INT_ERR; #endif - } + } #else /* R/O configuration */ - if (res == FR_OK) { /* Follow succeeded */ - if (!dir) { /* Current dir itself */ - res = FR_INVALID_NAME; - } else { - if (dir[DIR_Attr] & AM_DIR) /* It is a directory */ - res = FR_NO_FILE; + if (res == FR_OK) { /* Follow succeeded */ + dir = dj.dir; + if (!dir) { /* Current dir itself */ + res = FR_INVALID_NAME; + } else { + if (dir[DIR_Attr] & AM_DIR) /* It is a directory */ + res = FR_NO_FILE; + } } - } #endif - FREE_BUF(); + FREE_BUF(); - if (res == FR_OK) { - fp->flag = mode; /* File access mode */ - fp->sclust = LD_CLUST(dir); /* File start cluster */ - fp->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */ - fp->fptr = 0; /* File pointer */ - fp->dsect = 0; + if (res == FR_OK) { + fp->flag = mode; /* File access mode */ + fp->sclust = ld_clust(dj.fs, dir); /* File start cluster */ + fp->fsize = LD_DWORD(dir+DIR_FileSize); /* File size */ + fp->fptr = 0; /* File pointer */ + fp->dsect = 0; #if _USE_FASTSEEK - fp->cltbl = 0; /* Normal seek mode */ + fp->cltbl = 0; /* Normal seek mode */ #endif - fp->fs = dj.fs; fp->id = dj.fs->id; /* Validate file object */ + fp->fs = dj.fs; fp->id = dj.fs->id; /* Validate file object */ + } } LEAVE_FF(dj.fs, res); @@ -2377,9 +2426,9 @@ FRESULT f_read ( BYTE csect, *rbuff = buff; - *br = 0; /* Initialize byte counter */ + *br = 0; /* Clear read byte counter */ - res = validate(fp->fs, fp->id); /* Check validity */ + res = validate(fp); /* Check validity */ if (res != FR_OK) LEAVE_FF(fp->fs, res); if (fp->flag & FA__ERROR) /* Aborted file? */ LEAVE_FF(fp->fs, FR_INT_ERR); @@ -2443,7 +2492,7 @@ FRESULT f_read ( #endif fp->dsect = sect; } - rcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs)); /* Get partial sector data from sector buffer */ + rcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs)); /* Get partial sector data from sector buffer */ if (rcnt > btr) rcnt = btr; #if _FS_TINY if (move_window(fp->fs, fp->dsect)) /* Move sector window */ @@ -2479,9 +2528,9 @@ FRESULT f_write ( BYTE csect; - *bw = 0; /* Initialize byte counter */ + *bw = 0; /* Clear write byte counter */ - res = validate(fp->fs, fp->id); /* Check validity */ + res = validate(fp); /* Check validity */ if (res != FR_OK) LEAVE_FF(fp->fs, res); if (fp->flag & FA__ERROR) /* Aborted file? */ LEAVE_FF(fp->fs, FR_INT_ERR); @@ -2558,7 +2607,7 @@ FRESULT f_write ( #endif fp->dsect = sect; } - wcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */ + wcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */ if (wcnt > btw) wcnt = btw; #if _FS_TINY if (move_window(fp->fs, fp->dsect)) /* Move sector window */ @@ -2593,7 +2642,7 @@ FRESULT f_sync ( BYTE *dir; - res = validate(fp->fs, fp->id); /* Check validity of the object */ + res = validate(fp); /* Check validity of the object */ if (res == FR_OK) { if (fp->flag & FA__WRITTEN) { /* Has the file been written? */ #if !_FS_TINY /* Write-back dirty buffer */ @@ -2609,9 +2658,10 @@ FRESULT f_sync ( dir = fp->dir_ptr; dir[DIR_Attr] |= AM_ARC; /* Set archive bit */ ST_DWORD(dir+DIR_FileSize, fp->fsize); /* Update file size */ - ST_CLUST(dir, fp->sclust); /* Update start cluster */ + st_clust(dir, fp->sclust); /* Update start cluster */ tim = get_fattime(); /* Update updated time */ ST_DWORD(dir+DIR_WrtTime, tim); + ST_WORD(dir+DIR_LstAccDate, 0); fp->flag &= ~FA__WRITTEN; fp->fs->wflag = 1; res = sync(fp->fs); @@ -2637,21 +2687,26 @@ FRESULT f_close ( { FRESULT res; -#if _FS_READONLY - FATFS *fs = fp->fs; - res = validate(fs, fp->id); - if (res == FR_OK) fp->fs = 0; /* Discard file object */ - LEAVE_FF(fs, res); +#if _FS_READONLY + res = validate(fp); + { +#if _FS_REENTRANT + FATFS *fs = fp->fs; +#endif + if (res == FR_OK) fp->fs = 0; /* Discard file object */ + LEAVE_FF(fs, res); + } #else res = f_sync(fp); /* Flush cached data */ -#if _FS_SHARE +#if _FS_LOCK if (res == FR_OK) { /* Decrement open counter */ #if _FS_REENTRANT - res = validate(fp->fs, fp->id); + FATFS *fs = fp->fs;; + res = validate(fp); if (res == FR_OK) { - res = dec_lock(fp->lockid); - unlock_fs(fp->fs, FR_OK); + res = dec_lock(fp->lockid); + unlock_fs(fs, FR_OK); } #else res = dec_lock(fp->lockid); @@ -2704,7 +2759,7 @@ FRESULT f_chdir ( dj.fs->cdir = dj.sclust; /* Start directory itself */ } else { if (dj.dir[DIR_Attr] & AM_DIR) /* Reached to the directory */ - dj.fs->cdir = LD_CLUST(dj.dir); + dj.fs->cdir = ld_clust(dj.fs, dj.dir); else res = FR_NO_PATH; /* Reached but a file */ } @@ -2742,14 +2797,14 @@ FRESULT f_getcwd ( if (res != FR_OK) break; res = dir_read(&dj); if (res != FR_OK) break; - dj.sclust = LD_CLUST(dj.dir); /* Goto parent dir */ + dj.sclust = ld_clust(dj.fs, dj.dir); /* Goto parent dir */ res = dir_sdi(&dj, 0); if (res != FR_OK) break; do { /* Find the entry links to the child dir */ res = dir_read(&dj); if (res != FR_OK) break; - if (ccl == LD_CLUST(dj.dir)) break; /* Found the entry */ - res = dir_next(&dj, 0); + if (ccl == ld_clust(dj.fs, dj.dir)) break; /* Found the entry */ + res = dir_next(&dj, 0); } while (res == FR_OK); if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */ if (res != FR_OK) break; @@ -2803,7 +2858,7 @@ FRESULT f_lseek ( FRESULT res; - res = validate(fp->fs, fp->id); /* Check validity of the object */ + res = validate(fp); /* Check validity of the object */ if (res != FR_OK) LEAVE_FF(fp->fs, res); if (fp->flag & FA__ERROR) /* Check abort flag */ LEAVE_FF(fp->fs, FR_INT_ERR); @@ -2959,10 +3014,14 @@ FRESULT f_opendir ( ) { FRESULT res; + FATFS *fs; DEF_NAMEBUF; + if (!dj) return FR_INVALID_OBJECT; + res = chk_mounted(&path, &dj->fs, 0); + fs = dj->fs; if (res == FR_OK) { INIT_BUF(*dj); res = follow_path(dj, path); /* Follow the path to the directory */ @@ -2970,20 +3029,23 @@ FRESULT f_opendir ( if (res == FR_OK) { /* Follow completed */ if (dj->dir) { /* It is not the root dir */ if (dj->dir[DIR_Attr] & AM_DIR) { /* The object is a directory */ - dj->sclust = LD_CLUST(dj->dir); + dj->sclust = ld_clust(fs, dj->dir); } else { /* The object is not a directory */ res = FR_NO_PATH; } } if (res == FR_OK) { - dj->id = dj->fs->id; + dj->id = fs->id; res = dir_sdi(dj, 0); /* Rewind dir */ } } if (res == FR_NO_FILE) res = FR_NO_PATH; + if (res != FR_OK) dj->fs = 0; /* Invalidate the dir object if function failed */ + } else { + dj->fs = 0; } - LEAVE_FF(dj->fs, res); + LEAVE_FF(fs, res); } @@ -3002,7 +3064,7 @@ FRESULT f_readdir ( DEF_NAMEBUF; - res = validate(dj->fs, dj->id); /* Check validity of the object */ + res = validate(dj); /* Check validity of the object */ if (res == FR_OK) { if (!fno) { res = dir_sdi(dj, 0); /* Rewind the directory object */ @@ -3075,6 +3137,7 @@ FRESULT f_getfree ( ) { FRESULT res; + FATFS *fs; DWORD n, clst, sect, stat; UINT i; BYTE fat, *p; @@ -3082,32 +3145,33 @@ FRESULT f_getfree ( /* Get drive number */ res = chk_mounted(&path, fatfs, 0); + fs = *fatfs; if (res == FR_OK) { /* If free_clust is valid, return it without full cluster scan */ - if ((*fatfs)->free_clust <= (*fatfs)->n_fatent - 2) { - *nclst = (*fatfs)->free_clust; + if (fs->free_clust <= fs->n_fatent - 2) { + *nclst = fs->free_clust; } else { /* Get number of free clusters */ - fat = (*fatfs)->fs_type; + fat = fs->fs_type; n = 0; if (fat == FS_FAT12) { clst = 2; do { - stat = get_fat(*fatfs, clst); + stat = get_fat(fs, clst); if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } if (stat == 1) { res = FR_INT_ERR; break; } if (stat == 0) n++; - } while (++clst < (*fatfs)->n_fatent); + } while (++clst < fs->n_fatent); } else { - clst = (*fatfs)->n_fatent; - sect = (*fatfs)->fatbase; + clst = fs->n_fatent; + sect = fs->fatbase; i = 0; p = 0; do { if (!i) { - res = move_window(*fatfs, sect++); + res = move_window(fs, sect++); if (res != FR_OK) break; - p = (*fatfs)->win; - i = SS(*fatfs); + p = fs->win; + i = SS(fs); } if (fat == FS_FAT16) { if (LD_WORD(p) == 0) n++; @@ -3118,12 +3182,12 @@ FRESULT f_getfree ( } } while (--clst); } - (*fatfs)->free_clust = n; - if (fat == FS_FAT32) (*fatfs)->fsi_flag = 1; + fs->free_clust = n; + if (fat == FS_FAT32) fs->fsi_flag = 1; *nclst = n; } } - LEAVE_FF(*fatfs, res); + LEAVE_FF(fs, res); } @@ -3141,7 +3205,9 @@ FRESULT f_truncate ( DWORD ncl; - res = validate(fp->fs, fp->id); /* Check validity of the object */ + if (!fp) return FR_INVALID_OBJECT; + + res = validate(fp); /* Check validity of the object */ if (res == FR_OK) { if (fp->flag & FA__ERROR) { /* Check abort flag */ res = FR_INT_ERR; @@ -3198,7 +3264,7 @@ FRESULT f_unlink ( res = follow_path(&dj, path); /* Follow the file path */ if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT)) res = FR_INVALID_NAME; /* Cannot remove dot entry */ -#if _FS_SHARE +#if _FS_LOCK if (res == FR_OK) res = chk_lock(&dj, 2); /* Cannot remove open file */ #endif if (res == FR_OK) { /* The object is accessible */ @@ -3209,19 +3275,19 @@ FRESULT f_unlink ( if (dir[DIR_Attr] & AM_RDO) res = FR_DENIED; /* Cannot remove R/O object */ } - dclst = LD_CLUST(dir); + dclst = ld_clust(dj.fs, dir); if (res == FR_OK && (dir[DIR_Attr] & AM_DIR)) { /* Is it a sub-dir? */ if (dclst < 2) { res = FR_INT_ERR; } else { - mem_cpy(&sdj, &dj, sizeof(DIR)); /* Check if the sub-dir is empty or not */ + mem_cpy(&sdj, &dj, sizeof (DIR)); /* Check if the sub-dir is empty or not */ sdj.sclust = dclst; res = dir_sdi(&sdj, 2); /* Exclude dot entries */ if (res == FR_OK) { res = dir_read(&sdj); - if (res == FR_OK /* Not empty dir */ + if (res == FR_OK /* Not empty dir */ #if _FS_RPATH - || dclst == sdj.fs->cdir /* Current dir */ + || dclst == dj.fs->cdir /* Current dir */ #endif ) res = FR_DENIED; if (res == FR_NO_FILE) res = FR_OK; /* Empty */ @@ -3283,12 +3349,12 @@ FRESULT f_mkdir ( dir[DIR_Name] = '.'; dir[DIR_Attr] = AM_DIR; ST_DWORD(dir+DIR_WrtTime, tim); - ST_CLUST(dir, dcl); + st_clust(dir, dcl); mem_cpy(dir+SZ_DIR, dir, SZ_DIR); /* Create ".." entry */ dir[33] = '.'; pcl = dj.sclust; if (dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase) pcl = 0; - ST_CLUST(dir+SZ_DIR, pcl); + st_clust(dir+SZ_DIR, pcl); for (n = dj.fs->csize; n; n--) { /* Write dot entries and clear following sectors */ dj.fs->winsect = dsc++; dj.fs->wflag = 1; @@ -3304,7 +3370,7 @@ FRESULT f_mkdir ( dir = dj.dir; dir[DIR_Attr] = AM_DIR; /* Attribute */ ST_DWORD(dir+DIR_WrtTime, tim); /* Created time */ - ST_CLUST(dir, dcl); /* Table start cluster */ + st_clust(dir, dcl); /* Table start cluster */ dj.fs->wflag = 1; res = sync(dj.fs); } @@ -3361,7 +3427,7 @@ FRESULT f_chmod ( /*-----------------------------------------------------------------------*/ -/* Change Time-stamp */ +/* Change Timestamp */ /*-----------------------------------------------------------------------*/ FRESULT f_utime ( @@ -3424,7 +3490,7 @@ FRESULT f_rename ( res = follow_path(&djo, path_old); /* Check old object */ if (_FS_RPATH && res == FR_OK && (djo.fn[NS] & NS_DOT)) res = FR_INVALID_NAME; -#if _FS_SHARE +#if _FS_LOCK if (res == FR_OK) res = chk_lock(&djo, 2); #endif if (res == FR_OK) { /* Old object is found */ @@ -3432,11 +3498,11 @@ FRESULT f_rename ( res = FR_NO_FILE; } else { mem_cpy(buf, djo.dir+DIR_Attr, 21); /* Save the object information except for name */ - mem_cpy(&djn, &djo, sizeof(DIR)); /* Check new object */ + mem_cpy(&djn, &djo, sizeof (DIR)); /* Check new object */ res = follow_path(&djn, path_new); if (res == FR_OK) res = FR_EXIST; /* The new object name is already existing */ if (res == FR_NO_FILE) { /* Is it a valid path and no name collision? */ -/* Start critical section that any interruption or error can cause cross-link */ +/* Start critical section that an interruption or error can cause cross-link */ res = dir_register(&djn); /* Register the new entry */ if (res == FR_OK) { dir = djn.dir; /* Copy object information except for name */ @@ -3444,16 +3510,16 @@ FRESULT f_rename ( dir[DIR_Attr] = buf[0] | AM_ARC; djo.fs->wflag = 1; if (djo.sclust != djn.sclust && (dir[DIR_Attr] & AM_DIR)) { /* Update .. entry in the directory if needed */ - dw = clust2sect(djn.fs, LD_CLUST(dir)); + dw = clust2sect(djo.fs, ld_clust(djo.fs, dir)); if (!dw) { res = FR_INT_ERR; } else { - res = move_window(djn.fs, dw); - dir = djn.fs->win+SZ_DIR; /* .. entry */ + res = move_window(djo.fs, dw); + dir = djo.fs->win+SZ_DIR; /* .. entry */ if (res == FR_OK && dir[1] == '.') { - dw = (djn.fs->fs_type == FS_FAT32 && djn.sclust == djn.fs->dirbase) ? 0 : djn.sclust; - ST_CLUST(dir, dw); - djn.fs->wflag = 1; + dw = (djo.fs->fs_type == FS_FAT32 && djn.sclust == djo.fs->dirbase) ? 0 : djn.sclust; + st_clust(dir, dw); + djo.fs->wflag = 1; } } } @@ -3497,9 +3563,11 @@ FRESULT f_forward ( BYTE csect; - *bf = 0; /* Initialize byte counter */ + *bf = 0; /* Clear transfer byte counter */ + + if (!fp) return FR_INVALID_OBJECT; - res = validate(fp->fs, fp->id); /* Check validity of the object */ + res = validate(fp); /* Check validity of the object */ if (res != FR_OK) LEAVE_FF(fp->fs, res); if (fp->flag & FA__ERROR) /* Check error flag */ LEAVE_FF(fp->fs, FR_INT_ERR); @@ -3555,10 +3623,10 @@ FRESULT f_mkfs ( { static const WORD vst[] = { 1024, 512, 256, 128, 64, 32, 16, 8, 4, 2, 0}; static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512}; - BYTE fmt, md, *tbl; + BYTE fmt, md, sys, *tbl, pdrv, part; DWORD n_clst, vs, n, wsect; UINT i; - DWORD b_vol, b_fat, b_dir, b_data; /* Offset (LBA) */ + DWORD b_vol, b_fat, b_dir, b_data; /* LBA */ DWORD n_vol, n_rsv, n_fat, n_dir; /* Size */ FATFS *fs; DSTATUS stat; @@ -3566,25 +3634,39 @@ FRESULT f_mkfs ( /* Check mounted drive and clear work area */ if (drv >= _VOLUMES) return FR_INVALID_DRIVE; + if (sfd > 1) return FR_INVALID_PARAMETER; + if (au & (au - 1)) return FR_INVALID_PARAMETER; fs = FatFs[drv]; if (!fs) return FR_NOT_ENABLED; fs->fs_type = 0; - drv = LD2PD(drv); + pdrv = LD2PD(drv); /* Physical drive */ + part = LD2PT(drv); /* Partition (0:auto detect, 1-4:get from partition table)*/ /* Get disk statics */ - stat = disk_initialize(drv); + stat = disk_initialize(pdrv); if (stat & STA_NOINIT) return FR_NOT_READY; if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; #if _MAX_SS != 512 /* Get disk sector size */ - if (disk_ioctl(drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK) + if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > _MAX_SS) return FR_DISK_ERR; #endif - if (disk_ioctl(drv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128) - return FR_DISK_ERR; - b_vol = (sfd) ? 0 : 63; /* Volume start sector */ - n_vol -= b_vol; - if (au & (au - 1)) au = 0; /* Check validity of the AU size */ - if (!au) { /* AU auto selection */ + if (_MULTI_PARTITION && part) { + /* Get partition information from partition table in the MBR */ + if (disk_read(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR; + if (LD_WORD(fs->win+BS_55AA) != 0xAA55) return FR_MKFS_ABORTED; + tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE]; + if (!tbl[4]) return FR_MKFS_ABORTED; /* No partition? */ + b_vol = LD_DWORD(tbl+8); /* Volume start sector */ + n_vol = LD_DWORD(tbl+12); /* Volume size */ + } else { + /* Create a partition in this function */ + if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128) + return FR_DISK_ERR; + b_vol = (sfd) ? 0 : 63; /* Volume start sector */ + n_vol -= b_vol; /* Volume size */ + } + + if (!au) { /* AU auto selection */ vs = n_vol / (2000 / (SS(fs) / 512)); for (i = 0; vs < vst[i]; i++) ; au = cst[i]; @@ -3593,7 +3675,7 @@ FRESULT f_mkfs ( if (au == 0) au = 1; if (au > 128) au = 128; - /* Pre-compute number of clusters and FAT syb-type */ + /* Pre-compute number of clusters and FAT sub-type */ n_clst = n_vol / au; fmt = FS_FAT12; if (n_clst >= MIN_FAT16) fmt = FS_FAT16; @@ -3613,10 +3695,10 @@ FRESULT f_mkfs ( b_fat = b_vol + n_rsv; /* FAT area start sector */ b_dir = b_fat + n_fat * N_FATS; /* Directory area start sector */ b_data = b_dir + n_dir; /* Data area start sector */ - if (n_vol < b_data + au) return FR_MKFS_ABORTED; /* Too small volume */ + if (n_vol < b_data + au - b_vol) return FR_MKFS_ABORTED; /* Too small volume */ /* Align data start sector to erase block boundary (for flash memory media) */ - if (disk_ioctl(drv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1; + if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1; n = (b_data + n - 1) & ~(n - 1); /* Next nearest erase block from current data start */ n = (n - b_data) / N_FATS; if (fmt == FS_FAT32) { /* FAT32: Move FAT offset */ @@ -3632,36 +3714,42 @@ FRESULT f_mkfs ( || (fmt == FS_FAT32 && n_clst < MIN_FAT32)) return FR_MKFS_ABORTED; - /* Create partition table if required */ - if (sfd) { /* No partition table (SFD) */ - md = 0xF0; - } else { /* With partition table (FDISK) */ - DWORD n_disk = b_vol + n_vol; - - mem_set(fs->win, 0, SS(fs)); - tbl = fs->win+MBR_Table; - ST_DWORD(tbl, 0x00010180); /* Partition start in CHS */ - if (n_disk < 63UL * 255 * 1024) { /* Partition end in CHS */ - n_disk = n_disk / 63 / 255; - tbl[7] = (BYTE)n_disk; - tbl[6] = (BYTE)((n_disk >> 2) | 63); - } else { - ST_WORD(&tbl[6], 0xFFFF); /* CHS saturated */ - } - tbl[5] = 254; - if (fmt != FS_FAT32) /* System ID */ - tbl[4] = (n_vol < 0x10000) ? 0x04 : 0x06; - else - tbl[4] = 0x0c; - ST_DWORD(tbl+8, 63); /* Partition start in LBA */ - ST_DWORD(tbl+12, n_vol); /* Partition size in LBA */ - ST_WORD(fs->win+BS_55AA, 0xAA55); /* MBR signature */ - if (disk_write(drv, fs->win, 0, 1) != RES_OK) /* Put the MBR into first physical sector */ - return FR_DISK_ERR; + switch (fmt) { /* Determine system ID for partition table */ + case FS_FAT12: sys = 0x01; break; + case FS_FAT16: sys = (n_vol < 0x10000) ? 0x04 : 0x06; break; + default: sys = 0x0C; + } + + if (_MULTI_PARTITION && part) { + /* Update system ID in the partition table */ + tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE]; + tbl[4] = sys; + if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR; md = 0xF8; + } else { + if (sfd) { /* No partition table (SFD) */ + md = 0xF0; + } else { /* Create partition table (FDISK) */ + mem_set(fs->win, 0, SS(fs)); + tbl = fs->win+MBR_Table; /* Create partition table for single partition in the drive */ + tbl[1] = 1; /* Partition start head */ + tbl[2] = 1; /* Partition start sector */ + tbl[3] = 0; /* Partition start cylinder */ + tbl[4] = sys; /* System type */ + tbl[5] = 254; /* Partition end head */ + n = (b_vol + n_vol) / 63 / 255; + tbl[6] = (BYTE)((n >> 2) | 63); /* Partition end sector */ + tbl[7] = (BYTE)n; /* End cylinder */ + ST_DWORD(tbl+8, 63); /* Partition start in LBA */ + ST_DWORD(tbl+12, n_vol); /* Partition size in LBA */ + ST_WORD(fs->win+BS_55AA, 0xAA55); /* MBR signature */ + if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) /* Write it to the MBR sector */ + return FR_DISK_ERR; + md = 0xF8; + } } - /* Create volume boot record */ + /* Create BPB in the VBR */ tbl = fs->win; /* Clear sector */ mem_set(tbl, 0, SS(fs)); mem_cpy(tbl, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code, OEM name */ @@ -3699,10 +3787,10 @@ FRESULT f_mkfs ( mem_cpy(tbl+BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */ } ST_WORD(tbl+BS_55AA, 0xAA55); /* Signature (Offset is fixed here regardless of sector size) */ - if (disk_write(drv, tbl, b_vol, 1) != RES_OK) /* Write VBR */ + if (disk_write(pdrv, tbl, b_vol, 1) != RES_OK) /* Write it to the VBR sector */ return FR_DISK_ERR; if (fmt == FS_FAT32) /* Write backup VBR if needed (VBR+6) */ - disk_write(drv, tbl, b_vol + 6, 1); + disk_write(pdrv, tbl, b_vol + 6, 1); /* Initialize FAT area */ wsect = b_fat; @@ -3718,11 +3806,11 @@ FRESULT f_mkfs ( ST_DWORD(tbl+4, 0xFFFFFFFF); ST_DWORD(tbl+8, 0x0FFFFFFF); /* Reserve cluster #2 for root dir */ } - if (disk_write(drv, tbl, wsect++, 1) != RES_OK) + if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK) return FR_DISK_ERR; mem_set(tbl, 0, SS(fs)); /* Fill following FAT entries with zero */ for (n = 1; n < n_fat; n++) { /* This loop may take a time on FAT32 volume due to many single sector writes */ - if (disk_write(drv, tbl, wsect++, 1) != RES_OK) + if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK) return FR_DISK_ERR; } } @@ -3730,7 +3818,7 @@ FRESULT f_mkfs ( /* Initialize root directory */ i = (fmt == FS_FAT32) ? au : n_dir; do { - if (disk_write(drv, tbl, wsect++, 1) != RES_OK) + if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK) return FR_DISK_ERR; } while (--i); @@ -3739,7 +3827,7 @@ FRESULT f_mkfs ( DWORD eb[2]; eb[0] = wsect; eb[1] = wsect + (n_clst - ((fmt == FS_FAT32) ? 1 : 0)) * au - 1; - disk_ioctl(drv, CTRL_ERASE_SECTOR, eb); + disk_ioctl(pdrv, CTRL_ERASE_SECTOR, eb); } #endif @@ -3750,13 +3838,82 @@ FRESULT f_mkfs ( ST_DWORD(tbl+FSI_Free_Count, n_clst - 1); /* Number of free clusters */ ST_DWORD(tbl+FSI_Nxt_Free, 2); /* Last allocated cluster# */ ST_WORD(tbl+BS_55AA, 0xAA55); - disk_write(drv, tbl, b_vol + 1, 1); /* Write original (VBR+1) */ - disk_write(drv, tbl, b_vol + 7, 1); /* Write backup (VBR+7) */ + disk_write(pdrv, tbl, b_vol + 1, 1); /* Write original (VBR+1) */ + disk_write(pdrv, tbl, b_vol + 7, 1); /* Write backup (VBR+7) */ + } + + return (disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR; +} + + +#if _MULTI_PARTITION == 2 +/*-----------------------------------------------------------------------*/ +/* Divide Physical Drive */ +/*-----------------------------------------------------------------------*/ + +FRESULT f_fdisk ( + BYTE pdrv, /* Physical drive number */ + const DWORD szt[], /* Pointer to the size table for each partitions */ + void* work /* Pointer to the working buffer */ +) +{ + UINT i, n, sz_cyl, tot_cyl, b_cyl, e_cyl, p_cyl; + BYTE s_hd, e_hd, *p, *buf = (BYTE*)work; + DSTATUS stat; + DWORD sz_disk, sz_part, s_part; + + + stat = disk_initialize(pdrv); + if (stat & STA_NOINIT) return FR_NOT_READY; + if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; + if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR; + + /* Determine CHS in the table regardless of the drive geometry */ + for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ; + if (n == 256) n--; + e_hd = n - 1; + sz_cyl = 63 * n; + tot_cyl = sz_disk / sz_cyl; + + /* Create partition table */ + mem_set(buf, 0, _MAX_SS); + p = buf + MBR_Table; b_cyl = 0; + for (i = 0; i < 4; i++, p += SZ_PTE) { + p_cyl = (szt[i] <= 100) ? (DWORD)tot_cyl * szt[i] / 100 : szt[i] / sz_cyl; + if (!p_cyl) continue; + s_part = (DWORD)sz_cyl * b_cyl; + sz_part = (DWORD)sz_cyl * p_cyl; + if (i == 0) { /* Exclude first track of cylinder 0 */ + s_hd = 1; + s_part += 63; sz_part -= 63; + } else { + s_hd = 0; + } + e_cyl = b_cyl + p_cyl - 1; + if (e_cyl >= tot_cyl) return FR_INVALID_PARAMETER; + + /* Set partition table */ + p[1] = s_hd; /* Start head */ + p[2] = (BYTE)((b_cyl >> 2) + 1); /* Start sector */ + p[3] = (BYTE)b_cyl; /* Start cylinder */ + p[4] = 0x06; /* System type (temporary setting) */ + p[5] = e_hd; /* End head */ + p[6] = (BYTE)((e_cyl >> 2) + 63); /* End sector */ + p[7] = (BYTE)e_cyl; /* End cylinder */ + ST_DWORD(p + 8, s_part); /* Start sector in LBA */ + ST_DWORD(p + 12, sz_part); /* Partition size */ + + /* Next partition */ + b_cyl += p_cyl; } + ST_WORD(p, 0xAA55); - return (disk_ioctl(drv, CTRL_SYNC, (void*)0) == RES_OK) ? FR_OK : FR_DISK_ERR; + /* Write it to the MBR */ + return (disk_write(pdrv, buf, 0, 1) || disk_ioctl(pdrv, CTRL_SYNC, 0)) ? FR_DISK_ERR : FR_OK; } + +#endif /* _MULTI_PARTITION == 2 */ #endif /* _USE_MKFS && !_FS_READONLY */ @@ -3894,7 +4051,7 @@ int f_printf ( UINT i, j, w; ULONG v; TCHAR c, d, s[16], *p; - int res, cc; + int res, chc, cc; va_start(arp, str); @@ -3930,11 +4087,13 @@ int f_printf ( case 'S' : /* String */ p = va_arg(arp, TCHAR*); for (j = 0; p[j]; j++) ; - res = 0; - while (!(f & 2) && j++ < w) res += (cc = f_putc(' ', fil)); - res += (cc = f_puts(p, fil)); - while (j++ < w) res += (cc = f_putc(' ', fil)); - if (cc != EOF) cc = res; + chc = 0; + if (!(f & 2)) { + while (j++ < w) chc += (cc = f_putc(' ', fil)); + } + chc += (cc = f_puts(p, fil)); + while (j++ < w) chc += (cc = f_putc(' ', fil)); + if (cc != EOF) cc = chc; continue; case 'C' : /* Character */ cc = f_putc((TCHAR)va_arg(arp, int), fil); continue; @@ -3945,14 +4104,14 @@ int f_printf ( case 'D' : /* Signed decimal */ case 'U' : /* Unsigned decimal */ r = 10; break; - case 'X' : /* Hexadecimal */ + case 'X' : /* Hexdecimal */ r = 16; break; - default: /* Unknown type (passthrough) */ + default: /* Unknown type (pass-through) */ cc = f_putc(c, fil); continue; } /* Get an argument and put it in numeral */ - v = (f & 4) ? va_arg(arp, long) : ((d == 'D') ? (long)va_arg(arp, int) : va_arg(arp, unsigned int)); + v = (f & 4) ? (ULONG)va_arg(arp, long) : ((d == 'D') ? (ULONG)(long)va_arg(arp, int) : (ULONG)va_arg(arp, unsigned int)); if (d == 'D' && (v & 0x80000000)) { v = 0 - v; f |= 8; @@ -3962,7 +4121,7 @@ int f_printf ( d = (TCHAR)(v % r); v /= r; if (d > 9) d += (c == 'x') ? 0x27 : 0x07; s[i++] = d + '0'; - } while (v && i < sizeof(s) / sizeof(s[0])); + } while (v && i < sizeof s / sizeof s[0]); if (f & 8) s[i++] = '-'; j = i; d = (f & 1) ? '0' : ' '; res = 0; @@ -3978,4 +4137,3 @@ int f_printf ( #endif /* !_FS_READONLY */ #endif /* _USE_STRFUNC */ - diff --git a/Projects/Webserver/Lib/FATFs/ff.h b/Projects/Webserver/Lib/FATFs/ff.h index 6a4107cdf..627cbaabe 100644 --- a/Projects/Webserver/Lib/FATFs/ff.h +++ b/Projects/Webserver/Lib/FATFs/ff.h @@ -1,11 +1,11 @@ /*---------------------------------------------------------------------------/ -/ FatFs - FAT file system module include file R0.08b (C)ChaN, 2011 +/ FatFs - FAT file system module include file R0.09a (C)ChaN, 2012 /----------------------------------------------------------------------------/ / FatFs module is a generic FAT file system module for small embedded systems. / This is a free software that opened for education, research and commercial / developments under license policy of following terms. / -/ Copyright (C) 2011, ChaN, all right reserved. +/ Copyright (C) 2012, ChaN, all right reserved. / / * The FatFs module is a free software and there is NO WARRANTY. / * No restriction on use. You can use, modify and redistribute it for @@ -15,7 +15,7 @@ /----------------------------------------------------------------------------*/ #ifndef _FATFS -#define _FATFS 8237 /* Revision ID */ +#define _FATFS 4004 /* Revision ID */ #ifdef __cplusplus extern "C" { @@ -33,17 +33,17 @@ extern "C" { /* Definitions of volume management */ #if _MULTI_PARTITION /* Multiple partition configuration */ -#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive# */ -#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition# */ typedef struct { - BYTE pd; /* Physical drive# */ - BYTE pt; /* Partition # (0-3) */ + BYTE pd; /* Physical drive number */ + BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */ } PARTITION; -extern const PARTITION VolToPart[]; /* Volume - Physical location resolution table */ +extern PARTITION VolToPart[]; /* Volume - Partition resolution table */ +#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */ +#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */ -#else /* Single partition configuration */ -#define LD2PD(vol) (vol) /* Logical drive# is bound to the same physical drive# */ -#define LD2PT(vol) 0 /* Always mounts the 1st partition */ +#else /* Single partition configuration */ +#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */ +#define LD2PT(vol) 0 /* Always mounts the 1st partition or in SFD */ #endif @@ -84,7 +84,7 @@ typedef struct { WORD id; /* File system mount ID */ WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ #if _MAX_SS != 512 - WORD ssize; /* Bytes per sector (512,1024,2048,4096) */ + WORD ssize; /* Bytes per sector (512, 1024, 2048 or 4096) */ #endif #if _FS_REENTRANT _SYNC_t sobj; /* Identifier of sync object */ @@ -111,24 +111,24 @@ typedef struct { /* File object structure (FIL) */ typedef struct { - FATFS* fs; /* Pointer to the owner file system object */ - WORD id; /* Owner file system mount ID */ + FATFS* fs; /* Pointer to the related file system object */ + WORD id; /* File system mount ID of the related file system object */ BYTE flag; /* File status flags */ BYTE pad1; - DWORD fptr; /* File read/write pointer (0 on file open) */ + DWORD fptr; /* File read/write pointer (0ed on file open) */ DWORD fsize; /* File size */ - DWORD sclust; /* File start cluster (0 when fsize==0) */ - DWORD clust; /* Current cluster */ - DWORD dsect; /* Current data sector */ + DWORD sclust; /* File data start cluster (0:no data cluster, always 0 when fsize is 0) */ + DWORD clust; /* Current cluster of fpter */ + DWORD dsect; /* Current data sector of fpter */ #if !_FS_READONLY DWORD dir_sect; /* Sector containing the directory entry */ - BYTE* dir_ptr; /* Ponter to the directory entry in the window */ + BYTE* dir_ptr; /* Pointer to the directory entry in the window */ #endif #if _USE_FASTSEEK DWORD* cltbl; /* Pointer to the cluster link map table (null on file open) */ #endif -#if _FS_SHARE - UINT lockid; /* File lock ID (index of file semaphore table) */ +#if _FS_LOCK + UINT lockid; /* File lock ID (index of file semaphore table Files[]) */ #endif #if !_FS_TINY BYTE buf[_MAX_SS]; /* File data read/write buffer */ @@ -188,12 +188,13 @@ typedef enum { FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */ FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */ FR_NOT_ENABLED, /* (12) The volume has no work area */ - FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume on the physical drive */ + FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */ FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */ FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */ FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */ FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */ - FR_TOO_MANY_OPEN_FILES /* (18) Number of open files > _FS_SHARE */ + FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */ + FR_INVALID_PARAMETER /* (19) Given parameter is invalid */ } FRESULT; @@ -216,27 +217,28 @@ FRESULT f_sync (FIL*); /* Flush cached data of a writing file */ FRESULT f_unlink (const TCHAR*); /* Delete an existing file or directory */ FRESULT f_mkdir (const TCHAR*); /* Create a new directory */ FRESULT f_chmod (const TCHAR*, BYTE, BYTE); /* Change attribute of the file/dir */ -FRESULT f_utime (const TCHAR*, const FILINFO*); /* Change time-stamp of the file/dir */ +FRESULT f_utime (const TCHAR*, const FILINFO*); /* Change times-tamp of the file/dir */ FRESULT f_rename (const TCHAR*, const TCHAR*); /* Rename/Move a file or directory */ -FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*); /* Forward data to the stream */ -FRESULT f_mkfs (BYTE, BYTE, UINT); /* Create a file system on the drive */ FRESULT f_chdrive (BYTE); /* Change current drive */ FRESULT f_chdir (const TCHAR*); /* Change current directory */ FRESULT f_getcwd (TCHAR*, UINT); /* Get current directory */ +FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*); /* Forward data to the stream */ +FRESULT f_mkfs (BYTE, BYTE, UINT); /* Create a file system on the drive */ +FRESULT f_fdisk (BYTE, const DWORD[], void*); /* Divide a physical drive into some partitions */ int f_putc (TCHAR, FIL*); /* Put a character to the file */ int f_puts (const TCHAR*, FIL*); /* Put a string to the file */ int f_printf (FIL*, const TCHAR*, ...); /* Put a formatted string to the file */ TCHAR* f_gets (TCHAR*, int, FIL*); /* Get a string from the file */ -#ifndef EOF -#define EOF (-1) -#endif - #define f_eof(fp) (((fp)->fptr == (fp)->fsize) ? 1 : 0) #define f_error(fp) (((fp)->flag & FA__ERROR) ? 1 : 0) #define f_tell(fp) ((fp)->fptr) #define f_size(fp) ((fp)->fsize) +#ifndef EOF +#define EOF (-1) +#endif + @@ -308,7 +310,7 @@ int ff_del_syncobj (_SYNC_t); /* Delete a sync object */ #define AM_MASK 0x3F /* Mask of defined bits */ -/* Fast seek function */ +/* Fast seek feature */ #define CREATE_LINKMAP 0xFFFFFFFF @@ -333,4 +335,3 @@ int ff_del_syncobj (_SYNC_t); /* Delete a sync object */ #endif #endif /* _FATFS */ - diff --git a/Projects/Webserver/Lib/FATFs/ffconf.h b/Projects/Webserver/Lib/FATFs/ffconf.h index 782f2bd65..243a20fa2 100644 --- a/Projects/Webserver/Lib/FATFs/ffconf.h +++ b/Projects/Webserver/Lib/FATFs/ffconf.h @@ -1,5 +1,5 @@ /*---------------------------------------------------------------------------/ -/ FatFs - FAT file system module configuration file R0.08b (C)ChaN, 2011 +/ FatFs - FAT file system module configuration file R0.09a (C)ChaN, 2012 /----------------------------------------------------------------------------/ / / CAUTION! Do not forget to make clean the project after any changes to @@ -7,7 +7,7 @@ / /----------------------------------------------------------------------------*/ #ifndef _FFCONF -#define _FFCONF 8237 /* Revision ID */ +#define _FFCONF 4004 /* Revision ID */ /*---------------------------------------------------------------------------/ @@ -36,7 +36,7 @@ / 3: f_lseek is removed in addition to 2. */ -#define _USE_STRFUNC 0 /* 0:Disable or 1/2:Enable */ +#define _USE_STRFUNC 0 /* 0:Disable or 1-2:Enable */ /* To enable string functions, set _USE_STRFUNC to 1 or 2. */ @@ -137,7 +137,7 @@ / and GET_SECTOR_SIZE command must be implemented to the disk_ioctl function. */ -#define _MULTI_PARTITION 0 /* 0:Single partition or 1:Multiple partition */ +#define _MULTI_PARTITION 0 /* 0:Single partition, 1/2:Enable multiple partition */ /* When set to 0, each volume is bound to the same physical drive number and / it can mount only first primary partition. When it is set to 1, each volume / is tied to the partitions listed in VolToPart[]. */ @@ -181,9 +181,9 @@ / function must be added to the project. */ -#define _FS_SHARE 0 /* 0:Disable or >=1:Enable */ -/* To enable file sharing feature, set _FS_SHARE to 1 or greater. The value - defines how many files can be opened simultaneously. */ +#define _FS_LOCK 0 /* 0:Disable or >=1:Enable */ +/* To enable file lock control feature, set _FS_LOCK to 1 or greater. + The value defines how many files can be opened simultaneously. */ #endif /* _FFCONFIG */ -- cgit v1.2.3