Merge branch 'master' into developer

This commit is contained in:
Aurora 2016-09-08 16:11:56 +02:00
commit 72c8212a0e
5 changed files with 202 additions and 195 deletions

View File

@ -260,8 +260,20 @@ R0.12a (July 10, 2016)
Added support for creating exFAT volume with some changes of f_mkfs(). Added support for creating exFAT volume with some changes of f_mkfs().
Added a file open method FA_OPEN_APPEND. An f_lseek() following f_open() is no longer needed. Added a file open method FA_OPEN_APPEND. An f_lseek() following f_open() is no longer needed.
f_forward() is available regardless of _FS_TINY. f_forward() is available regardless of _FS_TINY.
Fixed f_mkfs() creates wrong volume. Fixed f_mkfs() creates wrong volume. (appeared at R0.12)
Fixed wrong memory read in create_name(). (appeared at R0.12)
Fixed compilation fails at some configurations, _USE_FASTSEEK and _USE_FORWARD. Fixed compilation fails at some configurations, _USE_FASTSEEK and _USE_FORWARD.
Fixed wrong memory read in create_name().
R0.12b (September 04, 2016)
Improved f_rename() to be able to rename objects with the same name but case.
Fixed an error in the case conversion teble of code page 866. (ff.c)
Fixed writing data is truncated at the file offset 4GiB on the exFAT volume. (appeared at R0.12)
Fixed creating a file in the root directory of exFAT volume can fail. (appeared at R0.12)
Fixed f_mkfs() creating exFAT volume with too small cluster size can collapse unallocated memory. (appeared at R0.12)
Fixed wrong object name can be returned when read directory at Unicode cfg. (appeared at R0.12)
Fixed large file allocation/removing on the exFAT volume collapses allocation bitmap. (appeared at R0.12)
Fixed some internal errors in f_expand() and f_lseek(). (appeared at R0.12)

View File

@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------/ /*----------------------------------------------------------------------------/
/ FatFs - Generic FAT file system module R0.12a / / FatFs - Generic FAT file system module R0.12b /
/-----------------------------------------------------------------------------/ /-----------------------------------------------------------------------------/
/ /
/ Copyright (C) 2016, ChaN, all right reserved. / Copyright (C) 2016, ChaN, all right reserved.
@ -28,7 +28,7 @@
---------------------------------------------------------------------------*/ ---------------------------------------------------------------------------*/
#if _FATFS != 80186 /* Revision ID */ #if _FATFS != 68020 /* Revision ID */
#error Wrong include file (ff.h). #error Wrong include file (ff.h).
#endif #endif
@ -396,7 +396,7 @@ typedef struct {
#define BPB_NumFATs 16 /* Number of FATs (BYTE) */ #define BPB_NumFATs 16 /* Number of FATs (BYTE) */
#define BPB_RootEntCnt 17 /* Size of root directory area for FAT12/16 [entry] (WORD) */ #define BPB_RootEntCnt 17 /* Size of root directory area for FAT12/16 [entry] (WORD) */
#define BPB_TotSec16 19 /* Volume size (16-bit) [sector] (WORD) */ #define BPB_TotSec16 19 /* Volume size (16-bit) [sector] (WORD) */
#define BPB_Media 21 /* Media descriptor (BYTE) */ #define BPB_Media 21 /* Media descriptor byte (BYTE) */
#define BPB_FATSz16 22 /* FAT size (16-bit) [sector] (WORD) */ #define BPB_FATSz16 22 /* FAT size (16-bit) [sector] (WORD) */
#define BPB_SecPerTrk 24 /* Track size for int13h [sector] (WORD) */ #define BPB_SecPerTrk 24 /* Track size for int13h [sector] (WORD) */
#define BPB_NumHeads 26 /* Number of heads for int13h (WORD) */ #define BPB_NumHeads 26 /* Number of heads for int13h (WORD) */
@ -409,6 +409,7 @@ typedef struct {
#define BS_VolLab 43 /* Volume label string (8-byte) */ #define BS_VolLab 43 /* Volume label string (8-byte) */
#define BS_FilSysType 54 /* File system type string (8-byte) */ #define BS_FilSysType 54 /* File system type string (8-byte) */
#define BS_BootCode 62 /* Boot code (448-byte) */ #define BS_BootCode 62 /* Boot code (448-byte) */
#define BS_55AA 510 /* Signature word (WORD) */
#define BPB_FATSz32 36 /* FAT32: FAT size [sector] (DWORD) */ #define BPB_FATSz32 36 /* FAT32: FAT size [sector] (DWORD) */
#define BPB_ExtFlags32 40 /* FAT32: Extended flags (WORD) */ #define BPB_ExtFlags32 40 /* FAT32: Extended flags (WORD) */
@ -462,8 +463,6 @@ typedef struct {
#define PTE_StLba 8 /* MBR PTE: Start in LBA */ #define PTE_StLba 8 /* MBR PTE: Start in LBA */
#define PTE_SizLba 12 /* MBR PTE: Size in LBA */ #define PTE_SizLba 12 /* MBR PTE: Size in LBA */
#define BS_55AA 510 /* Signature word (WORD) */
#define DIR_Name 0 /* Short file name (11-byte) */ #define DIR_Name 0 /* Short file name (11-byte) */
#define DIR_Attr 11 /* Attribute (BYTE) */ #define DIR_Attr 11 /* Attribute (BYTE) */
#define DIR_NTres 12 /* Lower case flag (BYTE) */ #define DIR_NTres 12 /* Lower case flag (BYTE) */
@ -1141,7 +1140,7 @@ DWORD find_bitmap ( /* 0:No free cluster, 2..:Free cluster found, 0xFFFFFFFF:Dis
if (clst >= fs->n_fatent - 2) clst = 0; if (clst >= fs->n_fatent - 2) clst = 0;
scl = val = clst; ctr = 0; scl = val = clst; ctr = 0;
for (;;) { for (;;) {
if (move_window(fs, fs->database + val / 8 / SS(fs)) != FR_OK) return 0xFFFFFFFF; if (move_window(fs, fs->database + val / 8 / SS(fs)) != FR_OK) return 0xFFFFFFFF; /* (assuming bitmap is located top of the cluster heap) */
i = val / 8 % SS(fs); bm = 1 << (val % 8); i = val / 8 % SS(fs); bm = 1 << (val % 8);
do { do {
do { do {
@ -1180,7 +1179,7 @@ FRESULT change_bitmap (
clst -= 2; /* The first bit corresponds to cluster #2 */ clst -= 2; /* The first bit corresponds to cluster #2 */
sect = fs->database + clst / 8 / SS(fs); /* Sector address */ sect = fs->database + clst / 8 / SS(fs); /* Sector address (assuming bitmap is located top of the cluster heap) */
i = clst / 8 % SS(fs); /* Byte offset in the sector */ i = clst / 8 % SS(fs); /* Byte offset in the sector */
bm = 1 << (clst % 8); /* Bit mask in the byte */ bm = 1 << (clst % 8); /* Bit mask in the byte */
for (;;) { for (;;) {
@ -1321,7 +1320,7 @@ DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk err
if (clst == 0) { /* Create a new chain */ if (clst == 0) { /* Create a new chain */
scl = fs->last_clst; /* Get suggested cluster to start at */ scl = fs->last_clst; /* Get suggested cluster to start from */
if (scl == 0 || scl >= fs->n_fatent) scl = 1; if (scl == 0 || scl >= fs->n_fatent) scl = 1;
} }
else { /* Stretch current chain */ else { /* Stretch current chain */
@ -1333,7 +1332,7 @@ DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk err
} }
#if _FS_EXFAT #if _FS_EXFAT
if (fs->fs_type == FS_EXFAT) { /* At the exFAT */ if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
ncl = find_bitmap(fs, scl, 1); /* Find a free cluster */ ncl = find_bitmap(fs, scl, 1); /* Find a free cluster */
if (ncl == 0 || ncl == 0xFFFFFFFF) return ncl; /* No free cluster or hard error? */ if (ncl == 0 || ncl == 0xFFFFFFFF) return ncl; /* No free cluster or hard error? */
res = change_bitmap(fs, ncl, 1, 1); /* Mark the cluster 'in use' */ res = change_bitmap(fs, ncl, 1, 1); /* Mark the cluster 'in use' */
@ -1349,7 +1348,7 @@ DWORD create_chain ( /* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk err
} }
} else } else
#endif #endif
{ /* At the FAT12/16/32 */ { /* On the FAT12/16/32 volume */
ncl = scl; /* Start cluster */ ncl = scl; /* Start cluster */
for (;;) { for (;;) {
ncl++; /* Next cluster */ ncl++; /* Next cluster */
@ -1775,7 +1774,7 @@ void gen_numname (
/* itoa (hexdecimal) */ /* itoa (hexdecimal) */
i = 7; i = 7;
do { do {
c = (seq % 16) + '0'; c = (BYTE)((seq % 16) + '0');
if (c > '9') c += 7; if (c > '9') c += 7;
ns[i--] = c; ns[i--] = c;
seq /= 16; seq /= 16;
@ -2105,7 +2104,7 @@ FRESULT dir_read (
c = dp->dir[DIR_Name]; /* Test for the entry type */ c = dp->dir[DIR_Name]; /* Test for the entry type */
if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of the directory */ if (c == 0) { res = FR_NO_FILE; break; } /* Reached to end of the directory */
#if _FS_EXFAT #if _FS_EXFAT
if (fs->fs_type == FS_EXFAT) { /* At the exFAT */ if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
if (_USE_LABEL && vol) { if (_USE_LABEL && vol) {
if (c == 0x83) break; /* Volume label entry? */ if (c == 0x83) break; /* Volume label entry? */
} else { } else {
@ -2120,7 +2119,7 @@ FRESULT dir_read (
} }
} else } else
#endif #endif
{ /* At the FAT12/16/32 */ { /* On the FAT12/16/32 volume */
dp->obj.attr = a = dp->dir[DIR_Attr] & AM_MASK; /* Get attribute */ dp->obj.attr = a = dp->dir[DIR_Attr] & AM_MASK; /* Get attribute */
#if _USE_LFN != 0 /* LFN configuration */ #if _USE_LFN != 0 /* LFN configuration */
if (c == DDEM || c == '.' || (int)((a & ~AM_ARC) == AM_VOL) != vol) { /* An entry without valid data */ if (c == DDEM || c == '.' || (int)((a & ~AM_ARC) == AM_VOL) != vol) { /* An entry without valid data */
@ -2129,7 +2128,7 @@ FRESULT dir_read (
if (a == AM_LFN) { /* An LFN entry is found */ if (a == AM_LFN) { /* An LFN entry is found */
if (c & LLEF) { /* Is it start of an LFN sequence? */ if (c & LLEF) { /* Is it start of an LFN sequence? */
sum = dp->dir[LDIR_Chksum]; sum = dp->dir[LDIR_Chksum];
c &= ~LLEF; ord = c; c &= (BYTE)~LLEF; ord = c;
dp->blk_ofs = dp->dptr; dp->blk_ofs = dp->dptr;
} }
/* Check LFN validity and capture it */ /* Check LFN validity and capture it */
@ -2178,7 +2177,7 @@ FRESULT dir_find ( /* FR_OK(0):succeeded, !=0:error */
res = dir_sdi(dp, 0); /* Rewind directory object */ res = dir_sdi(dp, 0); /* Rewind directory object */
if (res != FR_OK) return res; if (res != FR_OK) return res;
#if _FS_EXFAT #if _FS_EXFAT
if (fs->fs_type == FS_EXFAT) { /* At the exFAT */ if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
BYTE nc; BYTE nc;
UINT di, ni; UINT di, ni;
WORD hash = xname_sum(fs->lfnbuf); /* Hash value of the name to find */ WORD hash = xname_sum(fs->lfnbuf); /* Hash value of the name to find */
@ -2194,7 +2193,7 @@ FRESULT dir_find ( /* FR_OK(0):succeeded, !=0:error */
return res; return res;
} }
#endif #endif
/* At the FAT12/16/32 */ /* On the FAT12/16/32 volume */
#if _USE_LFN != 0 #if _USE_LFN != 0
ord = sum = 0xFF; dp->blk_ofs = 0xFFFFFFFF; /* Reset LFN sequence */ ord = sum = 0xFF; dp->blk_ofs = 0xFFFFFFFF; /* Reset LFN sequence */
#endif #endif
@ -2212,7 +2211,7 @@ FRESULT dir_find ( /* FR_OK(0):succeeded, !=0:error */
if (!(dp->fn[NSFLAG] & NS_NOLFN)) { if (!(dp->fn[NSFLAG] & NS_NOLFN)) {
if (c & LLEF) { /* Is it start of LFN sequence? */ if (c & LLEF) { /* Is it start of LFN sequence? */
sum = dp->dir[LDIR_Chksum]; sum = dp->dir[LDIR_Chksum];
c &= ~LLEF; ord = c; /* LFN start order */ c &= (BYTE)~LLEF; ord = c; /* LFN start order */
dp->blk_ofs = dp->dptr; /* Start offset of LFN */ dp->blk_ofs = dp->dptr; /* Start offset of LFN */
} }
/* Check validity of the LFN entry and compare it with given name */ /* Check validity of the LFN entry and compare it with given name */
@ -2258,7 +2257,7 @@ FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too many S
for (nlen = 0; fs->lfnbuf[nlen]; nlen++) ; /* Get lfn length */ for (nlen = 0; fs->lfnbuf[nlen]; nlen++) ; /* Get lfn length */
#if _FS_EXFAT #if _FS_EXFAT
if (fs->fs_type == FS_EXFAT) { /* At the exFAT */ if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
DIR dj; DIR dj;
nent = (nlen + 14) / 15 + 2; /* Number of entries to allocate (85+C0+C1s) */ nent = (nlen + 14) / 15 + 2; /* Number of entries to allocate (85+C0+C1s) */
@ -2284,7 +2283,7 @@ FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too many S
return FR_OK; return FR_OK;
} }
#endif #endif
/* At the FAT12/16/32 */ /* On the FAT12/16/32 volume */
mem_cpy(sn, dp->fn, 12); mem_cpy(sn, dp->fn, 12);
if (sn[NSFLAG] & NS_LOSS) { /* When LFN is out of 8.3 format, generate a numbered name */ if (sn[NSFLAG] & NS_LOSS) { /* When LFN is out of 8.3 format, generate a numbered name */
dp->fn[NSFLAG] = NS_NOLFN; /* Find only SFN */ dp->fn[NSFLAG] = NS_NOLFN; /* Find only SFN */
@ -2361,9 +2360,9 @@ FRESULT dir_remove ( /* FR_OK:Succeeded, FR_DISK_ERR:A disk error */
res = move_window(fs, dp->sect); res = move_window(fs, dp->sect);
if (res != FR_OK) break; if (res != FR_OK) break;
/* Mark an entry 'deleted' */ /* Mark an entry 'deleted' */
if (_FS_EXFAT && fs->fs_type == FS_EXFAT) { /* At the exFAT */ if (_FS_EXFAT && fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
dp->dir[XDIR_Type] &= 0x7F; dp->dir[XDIR_Type] &= 0x7F;
} else { /* At the FAT12/16/32 */ } else { /* On the FAT12/16/32 volume */
dp->dir[DIR_Name] = DDEM; dp->dir[DIR_Name] = DDEM;
} }
fs->wflag = 1; fs->wflag = 1;
@ -2413,12 +2412,12 @@ void get_fileinfo ( /* No return code */
#if _USE_LFN != 0 /* LFN configuration */ #if _USE_LFN != 0 /* LFN configuration */
#if _FS_EXFAT #if _FS_EXFAT
if (fs->fs_type == FS_EXFAT) { /* At the exFAT */ if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
get_xdir_info(fs->dirbuf, fno); get_xdir_info(fs->dirbuf, fno);
return; return;
} else } else
#endif #endif
{ /* At the FAT12/16/32 */ { /* On the FAT12/16/32 volume */
if (dp->blk_ofs != 0xFFFFFFFF) { /* Get LFN if available */ if (dp->blk_ofs != 0xFFFFFFFF) { /* Get LFN if available */
i = j = 0; i = j = 0;
while ((w = fs->lfnbuf[j++]) != 0) { /* Get an LFN character */ while ((w = fs->lfnbuf[j++]) != 0) { /* Get an LFN character */
@ -2628,7 +2627,7 @@ FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not create */
if (si) cf |= NS_LOSS | NS_LFN; if (si) cf |= NS_LOSS | NS_LFN;
while (di && lfn[di - 1] != '.') di--; /* Find extension (di<=si: no extension) */ while (di && lfn[di - 1] != '.') di--; /* Find extension (di<=si: no extension) */
b = i = 0; ni = 8; i = b = 0; ni = 8;
for (;;) { for (;;) {
w = lfn[si++]; /* Get an LFN character */ w = lfn[si++]; /* Get an LFN character */
if (!w) break; /* Break on end of the LFN */ if (!w) break; /* Break on end of the LFN */
@ -2955,7 +2954,7 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */
UINT i; UINT i;
/* Get logical drive number from the path name */ /* Get logical drive number */
*rfs = 0; *rfs = 0;
vol = get_ldnumber(path); vol = get_ldnumber(path);
if (vol < 0) return FR_INVALID_DRIVE; if (vol < 0) return FR_INVALID_DRIVE;
@ -2967,7 +2966,7 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */
ENTER_FF(fs); /* Lock the volume */ ENTER_FF(fs); /* Lock the volume */
*rfs = fs; /* Return pointer to the file system object */ *rfs = fs; /* Return pointer to the file system object */
mode &= ~FA_READ; /* Desired access mode, write access or not */ mode &= (BYTE)~FA_READ; /* Desired access mode, write access or not */
if (fs->fs_type) { /* If the volume has been mounted */ if (fs->fs_type) { /* If the volume has been mounted */
stat = disk_status(fs->drv); stat = disk_status(fs->drv);
if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized */ if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized */
@ -3045,7 +3044,7 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */
fs->volbase = bsect; fs->volbase = bsect;
fs->database = bsect + ld_dword(fs->win + BPB_DataOfsEx); fs->database = bsect + ld_dword(fs->win + BPB_DataOfsEx);
fs->fatbase = bsect + ld_dword(fs->win + BPB_FatOfsEx); fs->fatbase = bsect + ld_dword(fs->win + BPB_FatOfsEx);
if (maxlba < fs->database + nclst * fs->csize) return FR_NO_FILESYSTEM; /* (Volume size must not be smaller than the size requiered) */ if (maxlba < (QWORD)fs->database + nclst * fs->csize) return FR_NO_FILESYSTEM; /* (Volume size must not be smaller than the size requiered) */
fs->dirbase = ld_dword(fs->win + BPB_RootClusEx); fs->dirbase = ld_dword(fs->win + BPB_RootClusEx);
/* Check if bitmap location is in assumption (at the first cluster) */ /* Check if bitmap location is in assumption (at the first cluster) */
@ -3162,15 +3161,14 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */
static static
FRESULT validate ( /* Returns FR_OK or FR_INVALID_OBJECT */ FRESULT validate ( /* Returns FR_OK or FR_INVALID_OBJECT */
void* dfp, /* Pointer to the FIL/DIR object to check validity */ _FDID* obj, /* Pointer to the _OBJ, the 1st member in the FIL/DIR object, to check validity */
FATFS** fs /* Pointer to pointer to the owner file system object to return */ FATFS** fs /* Pointer to pointer to the owner file system object to return */
) )
{ {
_FDID *obj = (_FDID*)dfp; /* Assuming .obj in the FIL/DIR is the first member */
FRESULT res; FRESULT res;
if (!dfp || !obj->fs || !obj->fs->fs_type || obj->fs->id != obj->id || (disk_status(obj->fs->drv) & STA_NOINIT)) { if (!obj || !obj->fs || !obj->fs->fs_type || obj->fs->id != obj->id || (disk_status(obj->fs->drv) & STA_NOINIT)) {
*fs = 0; /* The object is invalid */ *fs = 0; /* The object is invalid */
res = FR_INVALID_OBJECT; res = FR_INVALID_OBJECT;
} else { } else {
@ -3208,6 +3206,7 @@ FRESULT f_mount (
const TCHAR *rp = path; const TCHAR *rp = path;
/* Get logical drive number */
vol = get_ldnumber(&rp); vol = get_ldnumber(&rp);
if (vol < 0) return FR_INVALID_DRIVE; if (vol < 0) return FR_INVALID_DRIVE;
cfs = FatFs[vol]; /* Pointer to fs object */ cfs = FatFs[vol]; /* Pointer to fs object */
@ -3261,7 +3260,7 @@ FRESULT f_open (
if (!fp) return FR_INVALID_OBJECT; if (!fp) return FR_INVALID_OBJECT;
/* Get logical drive number */ /* Get logical drive */
mode &= _FS_READONLY ? FA_READ : FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_CREATE_NEW | FA_OPEN_ALWAYS | FA_OPEN_APPEND | FA_SEEKEND; mode &= _FS_READONLY ? FA_READ : FA_READ | FA_WRITE | FA_CREATE_ALWAYS | FA_CREATE_NEW | FA_OPEN_ALWAYS | FA_OPEN_APPEND | FA_SEEKEND;
res = find_volume(&path, &fs, mode); res = find_volume(&path, &fs, mode);
if (res == FR_OK) { if (res == FR_OK) {
@ -3460,7 +3459,7 @@ FRESULT f_read (
*br = 0; /* Clear read byte counter */ *br = 0; /* Clear read byte counter */
res = validate(fp, &fs); res = validate(&fp->obj, &fs); /* Check validity of the file object */
if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */ if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */
if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */
remain = fp->obj.objsize - fp->fptr; remain = fp->obj.objsize - fp->fptr;
@ -3495,9 +3494,7 @@ FRESULT f_read (
if (csect + cc > fs->csize) { /* Clip at cluster boundary */ if (csect + cc > fs->csize) { /* Clip at cluster boundary */
cc = fs->csize - csect; cc = fs->csize - csect;
} }
if (disk_read(fs->drv, rbuff, sect, cc) != RES_OK) { if (disk_read(fs->drv, rbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR);
ABORT(fs, FR_DISK_ERR);
}
#if !_FS_READONLY && _FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */ #if !_FS_READONLY && _FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */
#if _FS_TINY #if _FS_TINY
if (fs->wflag && fs->winsect - sect < cc) { if (fs->wflag && fs->winsect - sect < cc) {
@ -3517,12 +3514,10 @@ FRESULT f_read (
#if !_FS_READONLY #if !_FS_READONLY
if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */
if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
fp->flag &= ~FA_DIRTY; fp->flag &= (BYTE)~FA_DIRTY;
} }
#endif #endif
if (disk_read(fs->drv, fp->buf, sect, 1) != RES_OK) { /* Fill sector cache */ if (disk_read(fs->drv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */
ABORT(fs, FR_DISK_ERR);
}
} }
#endif #endif
fp->sect = sect; fp->sect = sect;
@ -3563,7 +3558,7 @@ FRESULT f_write (
*bw = 0; /* Clear write byte counter */ *bw = 0; /* Clear write byte counter */
res = validate(fp, &fs); res = validate(&fp->obj, &fs); /* Check validity of the file object */
if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */ if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */
if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */
@ -3603,7 +3598,7 @@ FRESULT f_write (
#else #else
if (fp->flag & FA_DIRTY) { /* Write-back sector cache */ if (fp->flag & FA_DIRTY) { /* Write-back sector cache */
if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
fp->flag &= ~FA_DIRTY; fp->flag &= (BYTE)~FA_DIRTY;
} }
#endif #endif
sect = clust2sect(fs, fp->clust); /* Get current sector */ sect = clust2sect(fs, fp->clust); /* Get current sector */
@ -3614,9 +3609,7 @@ FRESULT f_write (
if (csect + cc > fs->csize) { /* Clip at cluster boundary */ if (csect + cc > fs->csize) { /* Clip at cluster boundary */
cc = fs->csize - csect; cc = fs->csize - csect;
} }
if (disk_write(fs->drv, wbuff, sect, cc) != RES_OK) { if (disk_write(fs->drv, wbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR);
ABORT(fs, FR_DISK_ERR);
}
#if _FS_MINIMIZE <= 2 #if _FS_MINIMIZE <= 2
#if _FS_TINY #if _FS_TINY
if (fs->winsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ if (fs->winsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */
@ -3626,7 +3619,7 @@ FRESULT f_write (
#else #else
if (fp->sect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */ if (fp->sect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */
mem_cpy(fp->buf, wbuff + ((fp->sect - sect) * SS(fs)), SS(fs)); mem_cpy(fp->buf, wbuff + ((fp->sect - sect) * SS(fs)), SS(fs));
fp->flag &= ~FA_DIRTY; fp->flag &= (BYTE)~FA_DIRTY;
} }
#endif #endif
#endif #endif
@ -3634,17 +3627,16 @@ FRESULT f_write (
continue; continue;
} }
#if _FS_TINY #if _FS_TINY
if (fp->fptr >= fp->obj.objsize) { /* Avoid silly cache filling at growing edge */ if (fp->fptr >= fp->obj.objsize) { /* Avoid silly cache filling on the growing edge */
if (sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR); if (sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR);
fs->winsect = sect; fs->winsect = sect;
} }
#else #else
if (fp->sect != sect) { /* Fill sector cache with file data */ if (fp->sect != sect && /* Fill sector cache with file data */
if (fp->fptr < fp->obj.objsize && fp->fptr < fp->obj.objsize &&
disk_read(fs->drv, fp->buf, sect, 1) != RES_OK) { disk_read(fs->drv, fp->buf, sect, 1) != RES_OK) {
ABORT(fs, FR_DISK_ERR); ABORT(fs, FR_DISK_ERR);
} }
}
#endif #endif
fp->sect = sect; fp->sect = sect;
} }
@ -3684,13 +3676,14 @@ FRESULT f_sync (
DEF_NAMBUF DEF_NAMBUF
#endif #endif
res = validate(fp, &fs); /* Check validity of the object */
res = validate(&fp->obj, &fs); /* Check validity of the file object */
if (res == FR_OK) { if (res == FR_OK) {
if (fp->flag & FA_MODIFIED) { /* Is there any change to the file? */ if (fp->flag & FA_MODIFIED) { /* Is there any change to the file? */
#if !_FS_TINY #if !_FS_TINY
if (fp->flag & FA_DIRTY) { /* Write-back cached data if needed */ if (fp->flag & FA_DIRTY) { /* Write-back cached data if needed */
if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) LEAVE_FF(fs, FR_DISK_ERR); if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) LEAVE_FF(fs, FR_DISK_ERR);
fp->flag &= ~FA_DIRTY; fp->flag &= (BYTE)~FA_DIRTY;
} }
#endif #endif
/* Update the directory entry */ /* Update the directory entry */
@ -3715,7 +3708,7 @@ FRESULT f_sync (
res = store_xdir(&dj); /* Restore it to the directory */ res = store_xdir(&dj); /* Restore it to the directory */
if (res == FR_OK) { if (res == FR_OK) {
res = sync_fs(fs); res = sync_fs(fs);
fp->flag &= ~FA_MODIFIED; fp->flag &= (BYTE)~FA_MODIFIED;
} }
} }
FREE_NAMBUF(); FREE_NAMBUF();
@ -3733,7 +3726,7 @@ FRESULT f_sync (
st_word(dir + DIR_LstAccDate, 0); st_word(dir + DIR_LstAccDate, 0);
fs->wflag = 1; fs->wflag = 1;
res = sync_fs(fs); /* Restore it to the directory */ res = sync_fs(fs); /* Restore it to the directory */
fp->flag &= ~FA_MODIFIED; fp->flag &= (BYTE)~FA_MODIFIED;
} }
} }
} }
@ -3763,7 +3756,7 @@ FRESULT f_close (
if (res == FR_OK) if (res == FR_OK)
#endif #endif
{ {
res = validate(fp, &fs); /* Lock volume */ res = validate(&fp->obj, &fs); /* Lock volume */
if (res == FR_OK) { if (res == FR_OK) {
#if _FS_LOCK != 0 #if _FS_LOCK != 0
res = dec_lock(fp->obj.lockid); /* Decrement file open counter */ res = dec_lock(fp->obj.lockid); /* Decrement file open counter */
@ -3796,10 +3789,11 @@ FRESULT f_chdrive (
int vol; int vol;
/* Get logical drive number */
vol = get_ldnumber(&path); vol = get_ldnumber(&path);
if (vol < 0) return FR_INVALID_DRIVE; if (vol < 0) return FR_INVALID_DRIVE;
CurrVol = (BYTE)vol; CurrVol = (BYTE)vol; /* Set it as current volume */
return FR_OK; return FR_OK;
} }
@ -3815,7 +3809,7 @@ FRESULT f_chdir (
FATFS *fs; FATFS *fs;
DEF_NAMBUF DEF_NAMBUF
/* Get logical drive number */ /* Get logical drive */
res = find_volume(&path, &fs, 0); res = find_volume(&path, &fs, 0);
if (res == FR_OK) { if (res == FR_OK) {
dj.obj.fs = fs; dj.obj.fs = fs;
@ -3874,7 +3868,7 @@ FRESULT f_getcwd (
*buff = 0; *buff = 0;
/* Get logical drive number */ /* Get logical drive */
res = find_volume((const TCHAR**)&buff, &fs, 0); /* Get current volume */ res = find_volume((const TCHAR**)&buff, &fs, 0); /* Get current volume */
if (res == FR_OK) { if (res == FR_OK) {
dj.obj.fs = fs; dj.obj.fs = fs;
@ -3951,7 +3945,7 @@ FRESULT f_lseek (
DWORD cl, pcl, ncl, tcl, dsc, tlen, ulen, *tbl; DWORD cl, pcl, ncl, tcl, dsc, tlen, ulen, *tbl;
#endif #endif
res = validate(fp, &fs); /* Check validity of the object */ res = validate(&fp->obj, &fs); /* Check validity of the file object */
if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */ if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */
#if _USE_FASTSEEK #if _USE_FASTSEEK
if (fp->cltbl) { /* Fast seek */ if (fp->cltbl) { /* Fast seek */
@ -3993,12 +3987,10 @@ FRESULT f_lseek (
#if !_FS_READONLY #if !_FS_READONLY
if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */
if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
fp->flag &= ~FA_DIRTY; fp->flag &= (BYTE)~FA_DIRTY;
} }
#endif #endif
if (disk_read(fs->drv, fp->buf, dsc, 1) != RES_OK) { /* Load current sector */ if (disk_read(fs->drv, fp->buf, dsc, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Load current sector */
ABORT(fs, FR_DISK_ERR);
}
#endif #endif
fp->sect = dsc; fp->sect = dsc;
} }
@ -4021,7 +4013,7 @@ FRESULT f_lseek (
bcs = (DWORD)fs->csize * SS(fs); /* Cluster size (byte) */ bcs = (DWORD)fs->csize * SS(fs); /* Cluster size (byte) */
if (ifptr > 0 && if (ifptr > 0 &&
(ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */ (ofs - 1) / bcs >= (ifptr - 1) / bcs) { /* When seek to same or following cluster, */
fp->fptr = (ifptr - 1) & ~(QWORD)(bcs - 1); /* start from the current cluster */ fp->fptr = (ifptr - 1) & ~(FSIZE_t)(bcs - 1); /* start from the current cluster */
ofs -= fp->fptr; ofs -= fp->fptr;
clst = fp->clust; clst = fp->clust;
} else { /* When seek to back cluster, */ } else { /* When seek to back cluster, */
@ -4045,13 +4037,15 @@ FRESULT f_lseek (
fp->obj.objsize = fp->fptr; fp->obj.objsize = fp->fptr;
fp->flag |= FA_MODIFIED; fp->flag |= FA_MODIFIED;
} }
clst = create_chain(&fp->obj, clst); /* Force stretch if in write mode */ clst = create_chain(&fp->obj, clst); /* Follow chain with forceed stretch */
if (clst == 0) { /* When disk gets full, clip file size */ if (clst == 0) { /* Clip file size in case of disk full */
ofs = 0; break; ofs = 0; break;
} }
} else } else
#endif #endif
{
clst = get_fat(&fp->obj, clst); /* Follow cluster chain if not in write mode */ clst = get_fat(&fp->obj, clst); /* Follow cluster chain if not in write mode */
}
if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR);
if (clst <= 1 || clst >= fs->n_fatent) ABORT(fs, FR_INT_ERR); if (clst <= 1 || clst >= fs->n_fatent) ABORT(fs, FR_INT_ERR);
fp->clust = clst; fp->clust = clst;
@ -4064,26 +4058,22 @@ FRESULT f_lseek (
} }
} }
} }
if (!_FS_READONLY && fp->fptr > fp->obj.objsize) { /* Set file change flag if the file size is extended */
fp->obj.objsize = fp->fptr;
fp->flag |= FA_MODIFIED;
}
if (fp->fptr % SS(fs) && nsect != fp->sect) { /* Fill sector cache if needed */ if (fp->fptr % SS(fs) && nsect != fp->sect) { /* Fill sector cache if needed */
#if !_FS_TINY #if !_FS_TINY
#if !_FS_READONLY #if !_FS_READONLY
if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */
if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
fp->flag &= ~FA_DIRTY; fp->flag &= (BYTE)~FA_DIRTY;
} }
#endif #endif
if (disk_read(fs->drv, fp->buf, nsect, 1) != RES_OK) { /* Fill sector cache */ if (disk_read(fs->drv, fp->buf, nsect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */
ABORT(fs, FR_DISK_ERR);
}
#endif #endif
fp->sect = nsect; fp->sect = nsect;
} }
#if !_FS_READONLY
if (fp->fptr > fp->obj.objsize) { /* Set file change flag if the file size is extended */
fp->obj.objsize = fp->fptr;
fp->flag |= FA_MODIFIED;
}
#endif
} }
LEAVE_FF(fs, res); LEAVE_FF(fs, res);
@ -4109,7 +4099,7 @@ FRESULT f_opendir (
if (!dp) return FR_INVALID_OBJECT; if (!dp) return FR_INVALID_OBJECT;
/* Get logical drive number */ /* Get logical drive */
obj = &dp->obj; obj = &dp->obj;
res = find_volume(&path, &fs, 0); res = find_volume(&path, &fs, 0);
if (res == FR_OK) { if (res == FR_OK) {
@ -4174,7 +4164,7 @@ FRESULT f_closedir (
FATFS *fs; FATFS *fs;
res = validate(dp, &fs); res = validate(&dp->obj, &fs); /* Check validity of the file object */
if (res == FR_OK) { if (res == FR_OK) {
#if _FS_LOCK != 0 #if _FS_LOCK != 0
if (dp->obj.lockid) { /* Decrement sub-directory open counter */ if (dp->obj.lockid) { /* Decrement sub-directory open counter */
@ -4209,7 +4199,7 @@ FRESULT f_readdir (
DEF_NAMBUF DEF_NAMBUF
res = validate(dp, &fs); /* Check validity of the object */ res = validate(&dp->obj, &fs); /* Check validity of the directory object */
if (res == FR_OK) { if (res == FR_OK) {
if (!fno) { if (!fno) {
res = dir_sdi(dp, 0); /* Rewind the directory object */ res = dir_sdi(dp, 0); /* Rewind the directory object */
@ -4297,7 +4287,7 @@ FRESULT f_stat (
DEF_NAMBUF DEF_NAMBUF
/* Get logical drive number */ /* Get logical drive */
res = find_volume(&path, &dj.obj.fs, 0); res = find_volume(&path, &dj.obj.fs, 0);
if (res == FR_OK) { if (res == FR_OK) {
INIT_NAMBUF(dj.obj.fs); INIT_NAMBUF(dj.obj.fs);
@ -4336,7 +4326,7 @@ FRESULT f_getfree (
_FDID obj; _FDID obj;
/* Get logical drive number */ /* Get logical drive */
res = find_volume(&path, &fs, 0); res = find_volume(&path, &fs, 0);
if (res == FR_OK) { if (res == FR_OK) {
*fatfs = fs; /* Return ptr to the fs object */ *fatfs = fs; /* Return ptr to the fs object */
@ -4418,8 +4408,8 @@ FRESULT f_truncate (
DWORD ncl; DWORD ncl;
res = validate(fp, &fs); /* Check validity of the object */ res = validate(&fp->obj, &fs); /* Check validity of the file object */
if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */ if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res);
if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */
if (fp->obj.objsize > fp->fptr) { if (fp->obj.objsize > fp->fptr) {
@ -4442,7 +4432,7 @@ FRESULT f_truncate (
if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) { if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) {
res = FR_DISK_ERR; res = FR_DISK_ERR;
} else { } else {
fp->flag &= ~FA_DIRTY; fp->flag &= (BYTE)~FA_DIRTY;
} }
} }
#endif #endif
@ -4473,7 +4463,7 @@ FRESULT f_unlink (
DEF_NAMBUF DEF_NAMBUF
/* Get logical drive number */ /* Get logical drive */
res = find_volume(&path, &fs, FA_WRITE); res = find_volume(&path, &fs, FA_WRITE);
dj.obj.fs = fs; dj.obj.fs = fs;
if (res == FR_OK) { if (res == FR_OK) {
@ -4567,7 +4557,7 @@ FRESULT f_mkdir (
DEF_NAMBUF DEF_NAMBUF
/* Get logical drive number */ /* Get logical drive */
res = find_volume(&path, &fs, FA_WRITE); res = find_volume(&path, &fs, FA_WRITE);
dj.obj.fs = fs; dj.obj.fs = fs;
if (res == FR_OK) { if (res == FR_OK) {
@ -4661,7 +4651,7 @@ FRESULT f_rename (
get_ldnumber(&path_new); /* Ignore drive number of new name */ get_ldnumber(&path_new); /* Ignore drive number of new name */
res = find_volume(&path_old, &fs, FA_WRITE); /* Get logical drive number of the old object */ res = find_volume(&path_old, &fs, FA_WRITE); /* Get logical drive of the old object */
if (res == FR_OK) { if (res == FR_OK) {
djo.obj.fs = fs; djo.obj.fs = fs;
INIT_NAMBUF(fs); INIT_NAMBUF(fs);
@ -4679,7 +4669,9 @@ FRESULT f_rename (
mem_cpy(buf, fs->dirbuf, SZDIRE * 2); /* Save 85+C0 entry of old object */ mem_cpy(buf, fs->dirbuf, SZDIRE * 2); /* Save 85+C0 entry of old object */
mem_cpy(&djn, &djo, sizeof djo); mem_cpy(&djn, &djo, sizeof djo);
res = follow_path(&djn, path_new); /* Make sure if new object name is not in use */ res = follow_path(&djn, path_new); /* Make sure if new object name is not in use */
if (res == FR_OK) res = FR_EXIST; /* Is new name already in use? */ if (res == FR_OK) { /* Is new name already in use by any other object? */
res = (djn.obj.sclust == djo.obj.sclust && djn.dptr == djo.dptr) ? FR_NO_FILE : FR_EXIST;
}
if (res == FR_NO_FILE) { /* It is a valid path and no name collision */ if (res == FR_NO_FILE) { /* It is a valid path and no name collision */
res = dir_register(&djn); /* Register the new entry */ res = dir_register(&djn); /* Register the new entry */
if (res == FR_OK) { if (res == FR_OK) {
@ -4698,7 +4690,9 @@ FRESULT f_rename (
mem_cpy(buf, djo.dir + DIR_Attr, 21); /* Save information about the object except name */ mem_cpy(buf, djo.dir + DIR_Attr, 21); /* Save information about the object except name */
mem_cpy(&djn, &djo, sizeof (DIR)); /* Duplicate the directory object */ mem_cpy(&djn, &djo, sizeof (DIR)); /* Duplicate the directory object */
res = follow_path(&djn, path_new); /* Make sure if new object name is not in use */ res = follow_path(&djn, path_new); /* Make sure if new object name is not in use */
if (res == FR_OK) res = FR_EXIST; /* Is new name already in use? */ if (res == FR_OK) { /* Is new name already in use by any other object? */
res = (djn.obj.sclust == djo.obj.sclust && djn.dptr == djo.dptr) ? FR_NO_FILE : FR_EXIST;
}
if (res == FR_NO_FILE) { /* It is a valid path and no name collision */ if (res == FR_NO_FILE) { /* It is a valid path and no name collision */
res = dir_register(&djn); /* Register the new entry */ res = dir_register(&djn); /* Register the new entry */
if (res == FR_OK) { if (res == FR_OK) {
@ -4761,7 +4755,7 @@ FRESULT f_chmod (
DEF_NAMBUF DEF_NAMBUF
res = find_volume(&path, &fs, FA_WRITE); /* Get logical drive number */ res = find_volume(&path, &fs, FA_WRITE); /* Get logical drive */
dj.obj.fs = fs; dj.obj.fs = fs;
if (res == FR_OK) { if (res == FR_OK) {
INIT_NAMBUF(fs); INIT_NAMBUF(fs);
@ -4805,7 +4799,7 @@ FRESULT f_utime (
DEF_NAMBUF DEF_NAMBUF
res = find_volume(&path, &fs, FA_WRITE); /* Get logical drive number */ res = find_volume(&path, &fs, FA_WRITE); /* Get logical drive */
dj.obj.fs = fs; dj.obj.fs = fs;
if (res == FR_OK) { if (res == FR_OK) {
INIT_NAMBUF(fs); INIT_NAMBUF(fs);
@ -4853,7 +4847,7 @@ FRESULT f_getlabel (
WCHAR w; WCHAR w;
#endif #endif
/* Get logical drive number */ /* Get logical drive */
res = find_volume(&path, &fs, 0); res = find_volume(&path, &fs, 0);
/* Get volume label */ /* Get volume label */
@ -4941,7 +4935,7 @@ FRESULT f_setlabel (
static const char badchr[] = "\"*+,.:;<=>\?[]|\x7F"; static const char badchr[] = "\"*+,.:;<=>\?[]|\x7F";
/* Get logical drive number */ /* Get logical drive */
res = find_volume(&label, &fs, FA_WRITE); res = find_volume(&label, &fs, FA_WRITE);
if (res != FR_OK) LEAVE_FF(fs, res); if (res != FR_OK) LEAVE_FF(fs, res);
dj.obj.fs = fs; dj.obj.fs = fs;
@ -4950,7 +4944,7 @@ FRESULT f_setlabel (
for (slen = 0; (UINT)label[slen] >= ' '; slen++) ; /* Get name length */ for (slen = 0; (UINT)label[slen] >= ' '; slen++) ; /* Get name length */
#if _FS_EXFAT #if _FS_EXFAT
if (fs->fs_type == FS_EXFAT) { /* At the exFAT */ if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
for (i = j = 0; i < slen; ) { /* Create volume label in directory form */ for (i = j = 0; i < slen; ) { /* Create volume label in directory form */
w = label[i++]; w = label[i++];
#if !_LFN_UNICODE #if !_LFN_UNICODE
@ -4967,7 +4961,7 @@ FRESULT f_setlabel (
slen = j; slen = j;
} else } else
#endif #endif
{ /* At the FAT12/16/32 */ { /* On the FAT12/16/32 volume */
for ( ; slen && label[slen - 1] == ' '; slen--) ; /* Remove trailing spaces */ for ( ; slen && label[slen - 1] == ' '; slen--) ; /* Remove trailing spaces */
if (slen) { /* Is there a volume label to be set? */ if (slen) { /* Is there a volume label to be set? */
dirvn[0] = 0; i = j = 0; /* Create volume label in directory form */ dirvn[0] = 0; i = j = 0; /* Create volume label in directory form */
@ -5008,7 +5002,7 @@ FRESULT f_setlabel (
res = dir_read(&dj, 1); /* Get volume label entry */ res = dir_read(&dj, 1); /* Get volume label entry */
if (res == FR_OK) { if (res == FR_OK) {
if (_FS_EXFAT && fs->fs_type == FS_EXFAT) { if (_FS_EXFAT && fs->fs_type == FS_EXFAT) {
dj.dir[XDIR_NumLabel] = slen / 2; /* Change the volume label */ dj.dir[XDIR_NumLabel] = (BYTE)(slen / 2); /* Change the volume label */
mem_cpy(dj.dir + XDIR_Label, dirvn, slen); mem_cpy(dj.dir + XDIR_Label, dirvn, slen);
} else { } else {
if (slen) { if (slen) {
@ -5028,7 +5022,7 @@ FRESULT f_setlabel (
mem_set(dj.dir, 0, SZDIRE); /* Clear the entry */ mem_set(dj.dir, 0, SZDIRE); /* Clear the entry */
if (_FS_EXFAT && fs->fs_type == FS_EXFAT) { if (_FS_EXFAT && fs->fs_type == FS_EXFAT) {
dj.dir[XDIR_Type] = 0x83; /* Create 83 entry */ dj.dir[XDIR_Type] = 0x83; /* Create 83 entry */
dj.dir[XDIR_NumLabel] = slen / 2; dj.dir[XDIR_NumLabel] = (BYTE)(slen / 2);
mem_cpy(dj.dir + XDIR_Label, dirvn, slen); mem_cpy(dj.dir + XDIR_Label, dirvn, slen);
} else { } else {
dj.dir[DIR_Attr] = AM_VOL; /* Create volume label entry */ dj.dir[DIR_Attr] = AM_VOL; /* Create volume label entry */
@ -5066,8 +5060,8 @@ FRESULT f_expand (
DWORD n, clst, stcl, scl, ncl, tcl, lclst; DWORD n, clst, stcl, scl, ncl, tcl, lclst;
res = validate(fp, &fs); /* Check validity of the object */ res = validate(&fp->obj, &fs); /* Check validity of the file object */
if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */ if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res);
if (fsz == 0 || fp->obj.objsize != 0 || !(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); if (fsz == 0 || fp->obj.objsize != 0 || !(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED);
#if _FS_EXFAT #if _FS_EXFAT
if (fs->fs_type != FS_EXFAT && fsz >= 0x100000000) LEAVE_FF(fs, FR_DENIED); /* Check if in size limit */ if (fs->fs_type != FS_EXFAT && fsz >= 0x100000000) LEAVE_FF(fs, FR_DENIED); /* Check if in size limit */
@ -5161,8 +5155,8 @@ FRESULT f_forward (
*bf = 0; /* Clear transfer byte counter */ *bf = 0; /* Clear transfer byte counter */
res = validate(fp, &fs); /* Check validity of the object */ res = validate(&fp->obj, &fs); /* Check validity of the file object */
if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res); /* Check validity */ if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res);
if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */
remain = fp->obj.objsize - fp->fptr; remain = fp->obj.objsize - fp->fptr;
@ -5191,7 +5185,7 @@ FRESULT f_forward (
#if !_FS_READONLY #if !_FS_READONLY
if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */ if (fp->flag & FA_DIRTY) { /* Write-back dirty sector cache */
if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); if (disk_write(fs->drv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
fp->flag &= ~FA_DIRTY; fp->flag &= (BYTE)~FA_DIRTY;
} }
#endif #endif
if (disk_read(fs->drv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); if (disk_read(fs->drv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
@ -5226,14 +5220,14 @@ FRESULT f_mkfs (
{ {
const UINT n_fats = 1; /* Number of FATs for FAT12/16/32 volume (1 or 2) */ const UINT n_fats = 1; /* Number of FATs for FAT12/16/32 volume (1 or 2) */
const UINT n_rootdir = 512; /* Number of root directory entries for FAT12/16 volume */ const UINT n_rootdir = 512; /* Number of root directory entries for FAT12/16 volume */
static const WORD cst[] = {1, 4, 16, 64, 256, 512, 0}; /* Cluster size boundary for FAT12/16 volume (4KS unit) */ static const WORD cst[] = {1, 4, 16, 64, 256, 512, 0}; /* Cluster size boundary for FAT12/16 volume (4Ks unit) */
static const WORD cst32[] = {1, 2, 4, 8, 16, 32, 0}; /* Cluster size boundary for FAT32 volume (128KS unit) */ static const WORD cst32[] = {1, 2, 4, 8, 16, 32, 0}; /* Cluster size boundary for FAT32 volume (128Ks unit) */
BYTE fmt, sys, *buf, *pte, pdrv, part; BYTE fmt, sys, *buf, *pte, pdrv, part;
WORD ss; WORD ss;
DWORD n, pau, n_clst, sz_blk, sect, szb_buf, sz_buf; DWORD szb_buf, sz_buf, sz_blk, n_clst, pau, sect, nsect, n;
DWORD b_vol, b_fat, b_data; /* Base LBA for volume, fat, data */ DWORD b_vol, b_fat, b_data; /* Base LBA for volume, fat, data */
DWORD sz_vol, sz_rsv, sz_fat, sz_dir; /* Size for volume, fat, dir, data */ DWORD sz_vol, sz_rsv, sz_fat, sz_dir; /* Size for volume, fat, dir, data */
UINT i, ns; UINT i;
int vol; int vol;
DSTATUS stat; DSTATUS stat;
#if _USE_TRIM || _FS_EXFAT #if _USE_TRIM || _FS_EXFAT
@ -5246,34 +5240,33 @@ FRESULT f_mkfs (
if (vol < 0) return FR_INVALID_DRIVE; if (vol < 0) return FR_INVALID_DRIVE;
if (FatFs[vol]) FatFs[vol]->fs_type = 0; /* Clear mounted volume */ if (FatFs[vol]) FatFs[vol]->fs_type = 0; /* Clear mounted volume */
pdrv = LD2PD(vol); /* Physical drive */ pdrv = LD2PD(vol); /* Physical drive */
part = LD2PT(vol); /* Partition (0:create as new, 1-4:get by partition table) */ part = LD2PT(vol); /* Partition (0:create as new, 1-4:get from partition table) */
/* Check physical drive status */ /* Check physical drive status */
stat = disk_initialize(pdrv); stat = disk_initialize(pdrv);
if (stat & STA_NOINIT) return FR_NOT_READY; if (stat & STA_NOINIT) return FR_NOT_READY;
if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_blk) != RES_OK || !sz_blk || sz_blk > 32768 || (sz_blk & (sz_blk - 1))) sz_blk = 1; if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_blk) != RES_OK || !sz_blk || sz_blk > 32768 || (sz_blk & (sz_blk - 1))) sz_blk = 1; /* Erase block to align data area */
#if _MAX_SS != _MIN_SS /* Get sector size of the medium */ #if _MAX_SS != _MIN_SS /* Get sector size of the medium */
if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &ss) != RES_OK) return FR_DISK_ERR; if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &ss) != RES_OK) return FR_DISK_ERR;
if (ss > _MAX_SS || ss < _MIN_SS || (ss & (ss - 1))) return FR_DISK_ERR; if (ss > _MAX_SS || ss < _MIN_SS || (ss & (ss - 1))) return FR_DISK_ERR;
#else #else
ss = _MAX_SS; ss = _MAX_SS;
#endif #endif
if ((au != 0 && au < ss) || (au & (au - 1))) return FR_INVALID_PARAMETER; /* Check if au is valid */ if ((au != 0 && au < ss) || au > 0x1000000 || (au & (au - 1))) return FR_INVALID_PARAMETER; /* Check if au is valid */
au /= ss; /* Cluster size in byte to in sector */ au /= ss; /* Cluster size in unit of sector */
if (au > 32768) return FR_INVALID_PARAMETER;
/* Set size and pointer of the working buffer */ /* Get working buffer */
buf = (BYTE*)work; /* Use given working buffer */ buf = (BYTE*)work; /* Working buffer */
if (len < ss) return FR_MKFS_ABORTED; sz_buf = len / ss; /* Size of working buffer (sector) */
szb_buf = len & ~(ss - 1); /* Round-down by sector size [byte] */ szb_buf = sz_buf * ss; /* Size of working buffer (byte) */
sz_buf = szb_buf / ss; /* Size of sector buffer [sector] */ if (!szb_buf) return FR_MKFS_ABORTED;
/* Determine where the volume to be located (b_vol, sz_vol) */ /* Determine where the volume to be located (b_vol, sz_vol) */
if (_MULTI_PARTITION && part != 0) { if (_MULTI_PARTITION && part != 0) {
/* Get partition information from partition table in the MBR */ /* Get partition information from partition table in the MBR */
if (disk_read(pdrv, buf, 0, 1) != RES_OK) return FR_DISK_ERR; /* Load MBR */ if (disk_read(pdrv, buf, 0, 1) != RES_OK) return FR_DISK_ERR; /* Load MBR */
if (ld_word(buf + BS_55AA) != 0xAA55) return FR_MKFS_ABORTED; /* Check MBR is valid */ if (ld_word(buf + BS_55AA) != 0xAA55) return FR_MKFS_ABORTED; /* Check if MBR is valid */
pte = buf + (MBR_Table + (part - 1) * SZ_PTE); pte = buf + (MBR_Table + (part - 1) * SZ_PTE);
if (!pte[PTE_System]) return FR_MKFS_ABORTED; /* No partition? */ if (!pte[PTE_System]) return FR_MKFS_ABORTED; /* No partition? */
b_vol = ld_dword(pte + PTE_StLba); /* Get volume start sector */ b_vol = ld_dword(pte + PTE_StLba); /* Get volume start sector */
@ -5285,16 +5278,16 @@ FRESULT f_mkfs (
if (sz_vol < b_vol) return FR_MKFS_ABORTED; if (sz_vol < b_vol) return FR_MKFS_ABORTED;
sz_vol -= b_vol; /* Volume size */ sz_vol -= b_vol; /* Volume size */
} }
if (sz_vol < 128) return FR_MKFS_ABORTED; /* Check volume size (>=128s) */ if (sz_vol < 128) return FR_MKFS_ABORTED; /* Check if volume size is >=128s */
/* Pre-determine the FAT type by argument */ /* Pre-determine the FAT type */
do { do {
if (_FS_EXFAT && (opt & FM_EXFAT)) { /* exFAT possible? */ if (_FS_EXFAT && (opt & FM_EXFAT)) { /* exFAT possible? */
if ((opt & FM_ANY) == FM_EXFAT || sz_vol >= 0x4000000 || au >= 256) { /* exFAT only, vol >= 64Ms or au >= 256s ? */ if ((opt & FM_ANY) == FM_EXFAT || sz_vol >= 0x4000000 || au > 128) { /* exFAT only, vol >= 64Ms or au > 128s ? */
fmt = FS_EXFAT; break; fmt = FS_EXFAT; break;
} }
} }
if (au >= 256) return FR_INVALID_PARAMETER; /* Too large au for FAT/FAT32 */ if (au > 128) return FR_INVALID_PARAMETER; /* Too large au for FAT/FAT32 */
if (opt & FM_FAT32) { /* FAT32 possible? */ if (opt & FM_FAT32) { /* FAT32 possible? */
if ((opt & FM_ANY) == FM_FAT32 || !(opt & FM_FAT)) { /* FAT32 only or no-FAT? */ if ((opt & FM_ANY) == FM_FAT32 || !(opt & FM_FAT)) { /* FAT32 only or no-FAT? */
fmt = FS_FAT32; break; fmt = FS_FAT32; break;
@ -5319,20 +5312,19 @@ FRESULT f_mkfs (
/* Determine FAT location, data location and number of clusters */ /* Determine FAT location, data location and number of clusters */
if (!au) { /* au auto-selection */ if (!au) { /* au auto-selection */
au = 8; au = 8;
if (sz_vol >= 0x80000) au = 64; /* >= 512KS */ if (sz_vol >= 0x80000) au = 64; /* >= 512Ks */
if (sz_vol >= 0x4000000) au = 256; /* >= 64MS */ if (sz_vol >= 0x4000000) au = 256; /* >= 64Ms */
} }
b_fat = b_vol + 32; /* FAT start at offset 32 */ b_fat = b_vol + 32; /* FAT start at offset 32 */
sz_fat = ((sz_vol / au + 2) * 4 + ss - 1) / ss; /* Numbef of FAT sectors */ sz_fat = ((sz_vol / au + 2) * 4 + ss - 1) / ss; /* Number of FAT sectors */
b_data = (b_fat + sz_fat + sz_blk - 1) & ~(sz_blk - 1); /* Align data area to the erase block boundary */ b_data = (b_fat + sz_fat + sz_blk - 1) & ~(sz_blk - 1); /* Align data area to the erase block boundary */
if (b_data >= sz_vol / 2) return FR_MKFS_ABORTED; /* Too small volume? */ if (b_data >= sz_vol / 2) return FR_MKFS_ABORTED; /* Too small volume? */
n_clst = (sz_vol - (b_data - b_vol)) / au; /* Nunber of clusters */ n_clst = (sz_vol - (b_data - b_vol)) / au; /* Number of clusters */
if (n_clst <16) return FR_MKFS_ABORTED; /* Too few clusters? */ if (n_clst <16) return FR_MKFS_ABORTED; /* Too few clusters? */
if (n_clst > MAX_EXFAT) return FR_MKFS_ABORTED; /* Too many clusters? */ if (n_clst > MAX_EXFAT) return FR_MKFS_ABORTED; /* Too many clusters? */
szb_bit = (n_clst + 7) / 8; /* Size of allocation bitmap */ szb_bit = (n_clst + 7) / 8; /* Size of allocation bitmap */
tbl[0] = (szb_bit + au * ss - 1) / (au * ss); /* Number of bitmap clusters */ tbl[0] = (szb_bit + au * ss - 1) / (au * ss); /* Number of allocation bitmap clusters */
tbl[2] = 1; /* Number of rootdir clusters */
/* Create a compressed up-case table */ /* Create a compressed up-case table */
sect = b_data + au * tbl[0]; /* Table start sector */ sect = b_data + au * tbl[0]; /* Table start sector */
@ -5363,30 +5355,31 @@ FRESULT f_mkfs (
sum = xsum32(buf[i + 1] = (BYTE)(ch >> 8), sum); sum = xsum32(buf[i + 1] = (BYTE)(ch >> 8), sum);
i += 2; szb_case += 2; i += 2; szb_case += 2;
if (!si || i == szb_buf) { /* Write buffered data when buffer full or end of process */ if (!si || i == szb_buf) { /* Write buffered data when buffer full or end of process */
ns = (i + ss - 1) / ss; n = (i + ss - 1) / ss;
if (disk_write(pdrv, buf, sect, ns) != RES_OK) return FR_DISK_ERR; if (disk_write(pdrv, buf, sect, n) != RES_OK) return FR_DISK_ERR;
sect += ns; i = 0; sect += n; i = 0;
} }
} while (si); } while (si);
tbl[1] = (szb_case + au * ss - 1) / (au * ss); /* Number of up-case clusters */ tbl[1] = (szb_case + au * ss - 1) / (au * ss); /* Number of up-case table clusters */
tbl[2] = 1; /* Number of root dir clusters */
/* Initialize the allocation bitmap */ /* Initialize the allocation bitmap */
sect = b_data; n = (szb_bit + ss - 1) / ss; /* Start of bitmap and number of the sectors */ sect = b_data; nsect = (szb_bit + ss - 1) / ss; /* Start of bitmap and number of sectors */
nb = tbl[0] + tbl[1] + tbl[2]; /* Number of clusters in-use by system */ nb = tbl[0] + tbl[1] + tbl[2]; /* Number of clusters in-use by system */
do { do {
mem_set(buf, 0, szb_buf); mem_set(buf, 0, szb_buf);
for (i = 0; nb >= 8 && i < szb_buf; buf[i++] = 0xFF, nb -= 8) ; for (i = 0; nb >= 8 && i < szb_buf; buf[i++] = 0xFF, nb -= 8) ;
for (b = 1; nb && i < szb_buf; buf[i] |= b, b <<= 1, nb--) ; for (b = 1; nb && i < szb_buf; buf[i] |= b, b <<= 1, nb--) ;
ns = (n > sz_buf) ? sz_buf : n; /* Write the buffered data */ n = (nsect > sz_buf) ? sz_buf : nsect; /* Write the buffered data */
if (disk_write(pdrv, buf, sect, ns) != RES_OK) return FR_DISK_ERR; if (disk_write(pdrv, buf, sect, n) != RES_OK) return FR_DISK_ERR;
sect += ns; n -= ns; sect += n; nsect -= n;
} while (n); } while (nsect);
/* Initialize the FAT */ /* Initialize the FAT */
sect = b_fat; n = sz_fat; /* Start of FAT and number of the sectors */ sect = b_fat; nsect = sz_fat; /* Start of FAT and number of FAT sectors */
j = nb = cl = 0; j = nb = cl = 0;
do { do {
mem_set(buf, 0, szb_buf); i = 0; mem_set(buf, 0, szb_buf); i = 0; /* Clear work area and reset write index */
if (cl == 0) { /* Set entry 0 and 1 */ if (cl == 0) { /* Set entry 0 and 1 */
st_dword(buf + i, 0xFFFFFFF8); i += 4; cl++; st_dword(buf + i, 0xFFFFFFF8); i += 4; cl++;
st_dword(buf + i, 0xFFFFFFFF); i += 4; cl++; st_dword(buf + i, 0xFFFFFFFF); i += 4; cl++;
@ -5398,13 +5391,13 @@ FRESULT f_mkfs (
} }
if (!nb && j < 3) nb = tbl[j++]; /* Next chain */ if (!nb && j < 3) nb = tbl[j++]; /* Next chain */
} while (nb && i < szb_buf); } while (nb && i < szb_buf);
ns = (n > sz_buf) ? sz_buf : n; /* Write the buffered data */ n = (nsect > sz_buf) ? sz_buf : nsect; /* Write the buffered data */
if (disk_write(pdrv, buf, sect, ns) != RES_OK) return FR_DISK_ERR; if (disk_write(pdrv, buf, sect, n) != RES_OK) return FR_DISK_ERR;
sect += ns; n -= ns; sect += n; nsect -= n;
} while (n); } while (nsect);
/* Initialize the root directory */ /* Initialize the root directory */
mem_set(buf, 0, ss); mem_set(buf, 0, szb_buf);
buf[SZDIRE * 0 + 0] = 0x83; /* 83 entry (volume label) */ buf[SZDIRE * 0 + 0] = 0x83; /* 83 entry (volume label) */
buf[SZDIRE * 1 + 0] = 0x81; /* 81 entry (allocation bitmap) */ buf[SZDIRE * 1 + 0] = 0x81; /* 81 entry (allocation bitmap) */
st_dword(buf + SZDIRE * 1 + 20, 2); st_dword(buf + SZDIRE * 1 + 20, 2);
@ -5413,13 +5406,13 @@ FRESULT f_mkfs (
st_dword(buf + SZDIRE * 2 + 4, sum); st_dword(buf + SZDIRE * 2 + 4, sum);
st_dword(buf + SZDIRE * 2 + 20, 2 + tbl[0]); st_dword(buf + SZDIRE * 2 + 20, 2 + tbl[0]);
st_dword(buf + SZDIRE * 2 + 24, szb_case); st_dword(buf + SZDIRE * 2 + 24, szb_case);
sect = b_data + au * (tbl[0] + tbl[1]); n = au; /* Start of directory and number of the sectors */ sect = b_data + au * (tbl[0] + tbl[1]); nsect = au; /* Start of the root directory and number of sectors */
do { /* Fill root direcotry sectors */ do { /* Fill root directory sectors */
ns = (n > sz_buf) ? sz_buf : n; n = (nsect > sz_buf) ? sz_buf : nsect;
if (disk_write(pdrv, buf, sect, ns) != RES_OK) return FR_DISK_ERR; if (disk_write(pdrv, buf, sect, n) != RES_OK) return FR_DISK_ERR;
sect += ns;
mem_set(buf, 0, ss); mem_set(buf, 0, ss);
} while (n -= ns); sect += n; nsect -= n;
} while (nsect);
/* Create two set of the exFAT VBR blocks */ /* Create two set of the exFAT VBR blocks */
sect = b_vol; sect = b_vol;
@ -5465,7 +5458,7 @@ FRESULT f_mkfs (
} }
} else } else
#endif #endif /* _FS_EXFAT */
{ /* Create an FAT12/16/32 volume */ { /* Create an FAT12/16/32 volume */
do { do {
pau = au; pau = au;
@ -5548,14 +5541,14 @@ FRESULT f_mkfs (
st_word(buf + BPB_BytsPerSec, ss); /* Sector size [byte] */ st_word(buf + BPB_BytsPerSec, ss); /* Sector size [byte] */
buf[BPB_SecPerClus] = (BYTE)pau; /* Cluster size [sector] */ buf[BPB_SecPerClus] = (BYTE)pau; /* Cluster size [sector] */
st_word(buf + BPB_RsvdSecCnt, (WORD)sz_rsv); /* Size of reserved area */ st_word(buf + BPB_RsvdSecCnt, (WORD)sz_rsv); /* Size of reserved area */
buf[BPB_NumFATs] = n_fats; /* Number of FATs */ buf[BPB_NumFATs] = (BYTE)n_fats; /* Number of FATs */
st_word(buf + BPB_RootEntCnt, (WORD)((fmt == FS_FAT32) ? 0 : n_rootdir)); /* Number of root directory entries */ st_word(buf + BPB_RootEntCnt, (WORD)((fmt == FS_FAT32) ? 0 : n_rootdir)); /* Number of root directory entries */
if (sz_vol < 0x10000) { if (sz_vol < 0x10000) {
st_word(buf + BPB_TotSec16, (WORD)sz_vol); /* Volume size in 16-bit LBA */ st_word(buf + BPB_TotSec16, (WORD)sz_vol); /* Volume size in 16-bit LBA */
} else { } else {
st_dword(buf + BPB_TotSec32, sz_vol); /* Volume size in 12-bit LBA */ st_dword(buf + BPB_TotSec32, sz_vol); /* Volume size in 32-bit LBA */
} }
buf[BPB_Media] = 0xF8; /* Media descriptor */ buf[BPB_Media] = 0xF8; /* Media descriptor byte */
st_word(buf + BPB_SecPerTrk, 63); /* Number of sectors per track (for int13) */ st_word(buf + BPB_SecPerTrk, 63); /* Number of sectors per track (for int13) */
st_word(buf + BPB_NumHeads, 255); /* Number of heads (for int13) */ st_word(buf + BPB_NumHeads, 255); /* Number of heads (for int13) */
st_dword(buf + BPB_HiddSec, b_vol); /* Volume offset in the physical drive [sector] */ st_dword(buf + BPB_HiddSec, b_vol); /* Volume offset in the physical drive [sector] */
@ -5592,8 +5585,8 @@ FRESULT f_mkfs (
} }
/* Initialize FAT area */ /* Initialize FAT area */
mem_set(buf, 0, szb_buf); mem_set(buf, 0, (UINT)szb_buf);
sect = b_fat; /* Start sector */ sect = b_fat; /* FAT start sector */
for (i = 0; i < n_fats; i++) { /* Initialize FATs each */ for (i = 0; i < n_fats; i++) { /* Initialize FATs each */
if (fmt == FS_FAT32) { if (fmt == FS_FAT32) {
st_dword(buf + 0, 0xFFFFFFF8); /* Entry 0 */ st_dword(buf + 0, 0xFFFFFFF8); /* Entry 0 */
@ -5602,22 +5595,22 @@ FRESULT f_mkfs (
} else { } else {
st_dword(buf + 0, (fmt == FS_FAT12) ? 0xFFFFF8 : 0xFFFFFFF8); /* Entry 0 and 1 */ st_dword(buf + 0, (fmt == FS_FAT12) ? 0xFFFFF8 : 0xFFFFFFF8); /* Entry 0 and 1 */
} }
n = sz_fat; /* Sector count of a FAT */ nsect = sz_fat; /* Number of FAT sectors */
do { /* Fill FAT sectors */ do { /* Fill FAT sectors */
ns = (n > sz_buf) ? sz_buf : n; n = (nsect > sz_buf) ? sz_buf : nsect;
if (disk_write(pdrv, buf, sect, ns) != RES_OK) return FR_DISK_ERR; if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) return FR_DISK_ERR;
sect += ns;
mem_set(buf, 0, ss); mem_set(buf, 0, ss);
} while (n -= ns); sect += n; nsect -= n;
} while (nsect);
} }
/* Initialize root directory (fill with zero) */ /* Initialize root directory (fill with zero) */
n = (fmt == FS_FAT32) ? pau : sz_dir; /* Sector count of root directory */ nsect = (fmt == FS_FAT32) ? pau : sz_dir; /* Number of root directory sectors */
do { do {
ns = (n > sz_buf) ? sz_buf : n; n = (nsect > sz_buf) ? sz_buf : nsect;
if (disk_write(pdrv, buf, sect, ns) != RES_OK) return FR_DISK_ERR; if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) return FR_DISK_ERR;
sect += ns; sect += n; nsect -= n;
} while (n -= ns); } while (nsect);
} }
/* Determine system ID in the partition table */ /* Determine system ID in the partition table */

View File

@ -1,5 +1,5 @@
/*----------------------------------------------------------------------------/ /*----------------------------------------------------------------------------/
/ FatFs - Generic FAT file system module R0.12a / / FatFs - Generic FAT file system module R0.12b /
/-----------------------------------------------------------------------------/ /-----------------------------------------------------------------------------/
/ /
/ Copyright (C) 2016, ChaN, all right reserved. / Copyright (C) 2016, ChaN, all right reserved.
@ -19,7 +19,7 @@
#ifndef _FATFS #ifndef _FATFS
#define _FATFS 80186 /* Revision ID */ #define _FATFS 68020 /* Revision ID */
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -159,7 +159,7 @@ typedef struct {
/* File object structure (FIL) */ /* File object structure (FIL) */
typedef struct { typedef struct {
_FDID obj; /* Object identifier */ _FDID obj; /* Object identifier (must be the 1st member to detect invalid object pointer) */
BYTE flag; /* File status flags */ BYTE flag; /* File status flags */
BYTE err; /* Abort flag (error code) */ BYTE err; /* Abort flag (error code) */
FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */ FSIZE_t fptr; /* File read/write pointer (Zeroed on file open) */

View File

@ -2,7 +2,7 @@
/ FatFs - FAT file system module configuration file / FatFs - FAT file system module configuration file
/---------------------------------------------------------------------------*/ /---------------------------------------------------------------------------*/
#define _FFCONF 80186 /* Revision ID */ #define _FFCONF 68020 /* Revision ID */
/*---------------------------------------------------------------------------/ /*---------------------------------------------------------------------------/
/ Function Configurations / Function Configurations
@ -204,14 +204,14 @@
#define _FS_TINY 0 #define _FS_TINY 0
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) /* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
/ At the tiny configuration, size of the file object (FIL) is reduced _MAX_SS bytes. / At the tiny configuration, size of file object (FIL) is reduced _MAX_SS bytes.
/ Instead of private sector buffer eliminated from the file object, common sector / Instead of private sector buffer eliminated from the file object, common sector
/ buffer in the file system object (FATFS) is used for the file data transfer. */ / buffer in the file system object (FATFS) is used for the file data transfer. */
#define _FS_EXFAT 0 #define _FS_EXFAT 0
/* This option switches support of exFAT file system in addition to the traditional /* This option switches support of exFAT file system. (0:Disable or 1:Enable)
/ FAT file system. (0:Disable or 1:Enable) To enable exFAT, also LFN must be enabled. / When enable exFAT, also LFN needs to be enabled. (_USE_LFN >= 1)
/ Note that enabling exFAT discards C89 compatibility. */ / Note that enabling exFAT discards C89 compatibility. */
@ -259,7 +259,9 @@
/ The _FS_TIMEOUT defines timeout period in unit of time tick. / The _FS_TIMEOUT defines timeout period in unit of time tick.
/ The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*, / The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
/ SemaphoreHandle_t and etc.. A header file for O/S definitions needs to be / SemaphoreHandle_t and etc.. A header file for O/S definitions needs to be
/ included somewhere in the scope of ff.c. */ / included somewhere in the scope of ff.h. */
/* #include <windows.h> // O/S definitions */
/*--- End of configuration options ---*/ /*--- End of configuration options ---*/

View File

@ -10,19 +10,19 @@
#define REG_SDCMDARG0 0x04 #define REG_SDCMDARG0 0x04
#define REG_SDCMDARG1 0x06 #define REG_SDCMDARG1 0x06
#define REG_SDSTOP 0x08 #define REG_SDSTOP 0x08
#define REG_SDBLKCOUNT 0x0a #define REG_SDBLKCOUNT 0x0A
#define REG_SDRESP0 0x0c #define REG_SDRESP0 0x0C
#define REG_SDRESP1 0x0e #define REG_SDRESP1 0x0E
#define REG_SDRESP2 0x10 #define REG_SDRESP2 0x10
#define REG_SDRESP3 0x12 #define REG_SDRESP3 0x12
#define REG_SDRESP4 0x14 #define REG_SDRESP4 0x14
#define REG_SDRESP5 0x16 #define REG_SDRESP5 0x16
#define REG_SDRESP6 0x18 #define REG_SDRESP6 0x18
#define REG_SDRESP7 0x1a #define REG_SDRESP7 0x1A
#define REG_SDSTATUS0 0x1c #define REG_SDSTATUS0 0x1C
#define REG_SDSTATUS1 0x1e #define REG_SDSTATUS1 0x1E
#define REG_SDIRMASK0 0x20 #define REG_SDIRMASK0 0x20
#define REG_SDIRMASK1 0x22 #define REG_SDIRMASK1 0x22
@ -32,9 +32,9 @@
#define REG_SDOPT 0x28 #define REG_SDOPT 0x28
#define REG_SDFIFO 0x30 #define REG_SDFIFO 0x30
#define REG_DATACTL 0xd8 #define REG_DATACTL 0xD8
#define REG_SDRESET 0xe0 #define REG_SDRESET 0xE0
#define REG_SDPROTECTED 0xf6 //bit 0 determines if sd is protected or not? #define REG_SDPROTECTED 0xF6 //bit 0 determines if sd is protected or not?
#define REG_DATACTL32 0x100 #define REG_DATACTL32 0x100
#define REG_SDBLKLEN32 0x104 #define REG_SDBLKLEN32 0x104
@ -42,7 +42,7 @@
#define REG_SDFIFO32 0x10C #define REG_SDFIFO32 0x10C
#define REG_CLK_AND_WAIT_CTL 0x138 #define REG_CLK_AND_WAIT_CTL 0x138
#define REG_RESET_SDIO 0x1e0 #define REG_RESET_SDIO 0x1E0
#define TMIO_STAT0_CMDRESPEND 0x0001 #define TMIO_STAT0_CMDRESPEND 0x0001
#define TMIO_STAT0_DATAEND 0x0004 #define TMIO_STAT0_DATAEND 0x0004
@ -66,7 +66,7 @@
#define TMIO_STAT1_CMD_BUSY 0x4000 #define TMIO_STAT1_CMD_BUSY 0x4000
#define TMIO_STAT1_ILL_ACCESS 0x8000 #define TMIO_STAT1_ILL_ACCESS 0x8000
#define TMIO_MASK_ALL 0x837f031d #define TMIO_MASK_ALL 0x837F031D
#define TMIO_MASK_GW (TMIO_STAT1_ILL_ACCESS | TMIO_STAT1_CMDTIMEOUT | TMIO_STAT1_TXUNDERRUN | TMIO_STAT1_RXOVERFLOW | \ #define TMIO_MASK_GW (TMIO_STAT1_ILL_ACCESS | TMIO_STAT1_CMDTIMEOUT | TMIO_STAT1_TXUNDERRUN | TMIO_STAT1_RXOVERFLOW | \
TMIO_STAT1_DATATIMEOUT | TMIO_STAT1_STOPBIT_ERR | TMIO_STAT1_CRCFAIL | TMIO_STAT1_CMD_IDX_ERR) TMIO_STAT1_DATATIMEOUT | TMIO_STAT1_STOPBIT_ERR | TMIO_STAT1_CRCFAIL | TMIO_STAT1_CMD_IDX_ERR)