[FatFS] Add error printing for important functions

So much needed
This commit is contained in:
Kostas Missos 2018-05-19 02:01:39 +03:00 committed by nwert
parent dcb77115c9
commit 526ffd4414

203
ipl/ff.c
View file

@ -3,6 +3,7 @@
/-----------------------------------------------------------------------------/ /-----------------------------------------------------------------------------/
/ /
/ Copyright (C) 2017, ChaN, all right reserved. / Copyright (C) 2017, ChaN, all right reserved.
/ Copyright (c) 2018 naehrwert
/ /
/ FatFs module is an open source software. Redistribution and use of FatFs in / FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided / source and binary forms, with or without modification, are permitted provided
@ -22,6 +23,11 @@
#include "ff.h" /* Declarations of FatFs API */ #include "ff.h" /* Declarations of FatFs API */
#include "diskio.h" /* Declarations of device I/O functions */ #include "diskio.h" /* Declarations of device I/O functions */
#include "gfx.h"
extern gfx_ctxt_t gfx_ctxt;
extern gfx_con_t gfx_con;
#define EFSPRINTF(text, ...) gfx_printf(&gfx_con, "\n\n%k[FatFS] "text"%k\n", 0xFF00FFFF, 0xFFFFFFFF)
//#define EFSPRINTF(...)
/*-------------------------------------------------------------------------- /*--------------------------------------------------------------------------
@ -3253,6 +3259,7 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */
stat = disk_status(fs->pdrv); stat = disk_status(fs->pdrv);
if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized */ if (!(stat & STA_NOINIT)) { /* and the physical drive is kept initialized */
if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check write protection if needed */ if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check write protection if needed */
EFSPRINTF("Error: Write protected!");
return FR_WRITE_PROTECTED; return FR_WRITE_PROTECTED;
} }
return FR_OK; /* The filesystem object is valid */ return FR_OK; /* The filesystem object is valid */
@ -3266,9 +3273,11 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */
fs->pdrv = LD2PD(vol); /* Bind the logical drive and a physical drive */ fs->pdrv = LD2PD(vol); /* Bind the logical drive and a physical drive */
stat = disk_initialize(fs->pdrv); /* Initialize the physical drive */ stat = disk_initialize(fs->pdrv); /* Initialize the physical drive */
if (stat & STA_NOINIT) { /* Check if the initialization succeeded */ if (stat & STA_NOINIT) { /* Check if the initialization succeeded */
EFSPRINTF("Error: Medium not ready or hard error!");
return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */ return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */
} }
if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check disk write protection if needed */ if (!FF_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check disk write protection if needed */
EFSPRINTF("Error: Write protected!");
return FR_WRITE_PROTECTED; return FR_WRITE_PROTECTED;
} }
#if FF_MAX_SS != FF_MIN_SS /* Get sector size (multiple sector size cfg only) */ #if FF_MAX_SS != FF_MIN_SS /* Get sector size (multiple sector size cfg only) */
@ -3291,8 +3300,14 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */
fmt = bsect ? check_fs(fs, bsect) : 3; /* Check the partition */ fmt = bsect ? check_fs(fs, bsect) : 3; /* Check the partition */
} while (LD2PT(vol) == 0 && fmt >= 2 && ++i < 4); } while (LD2PT(vol) == 0 && fmt >= 2 && ++i < 4);
} }
if (fmt == 4) return FR_DISK_ERR; /* An error occured in the disk I/O layer */ if (fmt == 4) {
if (fmt >= 2) return FR_NO_FILESYSTEM; /* No FAT volume is found */ EFSPRINTF("Error: Disk I/O error - Could not load boot record!");
return FR_DISK_ERR; /* An error occured in the disk I/O layer */
}
if (fmt >= 2) {
EFSPRINTF("Error: No FAT/FAT32/exFAT filesystem found!");
return FR_NO_FILESYSTEM; /* No FAT volume is found */
}
/* An FAT volume is found (bsect). Following code initializes the filesystem object */ /* An FAT volume is found (bsect). Following code initializes the filesystem object */
@ -3303,36 +3318,58 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */
for (i = BPB_ZeroedEx; i < BPB_ZeroedEx + 53 && fs->win[i] == 0; i++) ; /* Check zero filler */ for (i = BPB_ZeroedEx; i < BPB_ZeroedEx + 53 && fs->win[i] == 0; i++) ; /* Check zero filler */
if (i < BPB_ZeroedEx + 53) return FR_NO_FILESYSTEM; if (i < BPB_ZeroedEx + 53) return FR_NO_FILESYSTEM;
if (ld_word(fs->win + BPB_FSVerEx) != 0x100) return FR_NO_FILESYSTEM; /* Check exFAT version (must be version 1.0) */ if (ld_word(fs->win + BPB_FSVerEx) != 0x100) {
EFSPRINTF("Error: exFAT - Version check failed!");
return FR_NO_FILESYSTEM; /* Check exFAT version (must be version 1.0) */
}
if (1 << fs->win[BPB_BytsPerSecEx] != SS(fs)) { /* (BPB_BytsPerSecEx must be equal to the physical sector size) */ if (1 << fs->win[BPB_BytsPerSecEx] != SS(fs)) { /* (BPB_BytsPerSecEx must be equal to the physical sector size) */
EFSPRINTF("Error: exFAT - Bytes per sector does not match physical sector size!");
return FR_NO_FILESYSTEM; return FR_NO_FILESYSTEM;
} }
maxlba = ld_qword(fs->win + BPB_TotSecEx) + bsect; /* Last LBA + 1 of the volume */ maxlba = ld_qword(fs->win + BPB_TotSecEx) + bsect; /* Last LBA + 1 of the volume */
if (maxlba >= 0x100000000) return FR_NO_FILESYSTEM; /* (It cannot be handled in 32-bit LBA) */ if (maxlba >= 0x100000000) {
EFSPRINTF("Error: exFAT - Cannot handle volume LBA with 32-bit LBA!");
return FR_NO_FILESYSTEM; /* (It cannot be handled in 32-bit LBA) */
}
fs->fsize = ld_dword(fs->win + BPB_FatSzEx); /* Number of sectors per FAT */ fs->fsize = ld_dword(fs->win + BPB_FatSzEx); /* Number of sectors per FAT */
fs->n_fats = fs->win[BPB_NumFATsEx]; /* Number of FATs */ fs->n_fats = fs->win[BPB_NumFATsEx]; /* Number of FATs */
if (fs->n_fats != 1) return FR_NO_FILESYSTEM; /* (Supports only 1 FAT) */ if (fs->n_fats != 1) {
EFSPRINTF("Error: exFAT - Multiple or no file allocation tables found!");
return FR_NO_FILESYSTEM; /* (Supports only 1 FAT) */
}
fs->csize = 1 << fs->win[BPB_SecPerClusEx]; /* Cluster size */ fs->csize = 1 << fs->win[BPB_SecPerClusEx]; /* Cluster size */
if (fs->csize == 0) return FR_NO_FILESYSTEM; /* (Must be 1..32768) */ if (fs->csize == 0) {
EFSPRINTF("Error: exFAT - Cluster size is not between 1KB - 32KB!");
return FR_NO_FILESYSTEM; /* (Must be 1..32768) */
}
nclst = ld_dword(fs->win + BPB_NumClusEx); /* Number of clusters */ nclst = ld_dword(fs->win + BPB_NumClusEx); /* Number of clusters */
if (nclst > MAX_EXFAT) return FR_NO_FILESYSTEM; /* (Too many clusters) */ if (nclst > MAX_EXFAT) {
EFSPRINTF("Error: exFAT - Total clusters exceed allowed!");
return FR_NO_FILESYSTEM; /* (Too many clusters) */
}
fs->n_fatent = nclst + 2; fs->n_fatent = nclst + 2;
/* Boundaries and Limits */ /* Boundaries and Limits */
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 < (QWORD)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) {
EFSPRINTF("Error: exFAT - Volume size is lower than required!");
return FR_NO_FILESYSTEM; /* (Volume size must not be smaller than the size required) */
}
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) */
if (move_window(fs, clst2sect(fs, fs->dirbase)) != FR_OK) return FR_DISK_ERR; if (move_window(fs, clst2sect(fs, fs->dirbase)) != FR_OK) {
EFSPRINTF("Error: exFAT - Bitmap location not at first cluster!");
return FR_DISK_ERR;
}
for (i = 0; i < SS(fs); i += SZDIRE) { for (i = 0; i < SS(fs); i += SZDIRE) {
if (fs->win[i] == 0x81 && ld_dword(fs->win + i + 20) == 2) break; /* 81 entry with cluster #2? */ if (fs->win[i] == 0x81 && ld_dword(fs->win + i + 20) == 2) break; /* 81 entry with cluster #2? */
} }
@ -3344,38 +3381,62 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */
} else } else
#endif /* FF_FS_EXFAT */ #endif /* FF_FS_EXFAT */
{ {
if (ld_word(fs->win + BPB_BytsPerSec) != SS(fs)) return FR_NO_FILESYSTEM; /* (BPB_BytsPerSec must be equal to the physical sector size) */ if (ld_word(fs->win + BPB_BytsPerSec) != SS(fs)) {
EFSPRINTF("Error: FAT - Bytes per sector does not match physical sector size!");
return FR_NO_FILESYSTEM; /* (BPB_BytsPerSec must be equal to the physical sector size) */
}
fasize = ld_word(fs->win + BPB_FATSz16); /* Number of sectors per FAT */ fasize = ld_word(fs->win + BPB_FATSz16); /* Number of sectors per FAT */
if (fasize == 0) fasize = ld_dword(fs->win + BPB_FATSz32); if (fasize == 0) fasize = ld_dword(fs->win + BPB_FATSz32);
fs->fsize = fasize; fs->fsize = fasize;
fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FATs */ fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FATs */
if (fs->n_fats != 1 && fs->n_fats != 2) return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */ if (fs->n_fats != 1 && fs->n_fats != 2) {
EFSPRINTF("Error: FAT - No or more than 2 file allocation tables found!");
return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */
}
fasize *= fs->n_fats; /* Number of sectors for FAT area */ fasize *= fs->n_fats; /* Number of sectors for FAT area */
fs->csize = fs->win[BPB_SecPerClus]; /* Cluster size */ fs->csize = fs->win[BPB_SecPerClus]; /* Cluster size */
if (fs->csize == 0 || (fs->csize & (fs->csize - 1))) return FR_NO_FILESYSTEM; /* (Must be power of 2) */ if (fs->csize == 0 || (fs->csize & (fs->csize - 1))) {
EFSPRINTF("Error: FAT - Cluster size is not a power of 2!");
return FR_NO_FILESYSTEM; /* (Must be power of 2) */
}
fs->n_rootdir = ld_word(fs->win + BPB_RootEntCnt); /* Number of root directory entries */ fs->n_rootdir = ld_word(fs->win + BPB_RootEntCnt); /* Number of root directory entries */
if (fs->n_rootdir % (SS(fs) / SZDIRE)) return FR_NO_FILESYSTEM; /* (Must be sector aligned) */ if (fs->n_rootdir % (SS(fs) / SZDIRE)) {
EFSPRINTF("Error: FAT - Root directory entries are not sector aligned!");
return FR_NO_FILESYSTEM; /* (Must be sector aligned) */
}
tsect = ld_word(fs->win + BPB_TotSec16); /* Number of sectors on the volume */ tsect = ld_word(fs->win + BPB_TotSec16); /* Number of sectors on the volume */
if (tsect == 0) tsect = ld_dword(fs->win + BPB_TotSec32); if (tsect == 0) tsect = ld_dword(fs->win + BPB_TotSec32);
nrsv = ld_word(fs->win + BPB_RsvdSecCnt); /* Number of reserved sectors */ nrsv = ld_word(fs->win + BPB_RsvdSecCnt); /* Number of reserved sectors */
if (nrsv == 0) return FR_NO_FILESYSTEM; /* (Must not be 0) */ if (nrsv == 0) {
EFSPRINTF("Error: FAT - Zero reserved sectors!");
return FR_NO_FILESYSTEM; /* (Must not be 0) */
}
/* Determine the FAT sub type */ /* Determine the FAT sub type */
sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZDIRE); /* RSV + FAT + DIR */ sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZDIRE); /* RSV + FAT + DIR */
if (tsect < sysect) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ if (tsect < sysect) {
EFSPRINTF("Error: FAT - Invalid volume size!");
return FR_NO_FILESYSTEM; /* (Invalid volume size) */
}
nclst = (tsect - sysect) / fs->csize; /* Number of clusters */ nclst = (tsect - sysect) / fs->csize; /* Number of clusters */
if (nclst == 0) return FR_NO_FILESYSTEM; /* (Invalid volume size) */ if (nclst == 0) {
EFSPRINTF("Error: FAT - Invalid volume size!");
return FR_NO_FILESYSTEM; /* (Invalid volume size) */
}
fmt = 0; fmt = 0;
if (nclst <= MAX_FAT32) fmt = FS_FAT32; if (nclst <= MAX_FAT32) fmt = FS_FAT32;
if (nclst <= MAX_FAT16) fmt = FS_FAT16; if (nclst <= MAX_FAT16) fmt = FS_FAT16;
if (nclst <= MAX_FAT12) fmt = FS_FAT12; if (nclst <= MAX_FAT12) fmt = FS_FAT12;
if (fmt == 0) return FR_NO_FILESYSTEM; if (fmt == 0) {
EFSPRINTF("Error: FAT - Not compatible FAT12/16/32 filesystem!");
return FR_NO_FILESYSTEM;
}
/* Boundaries and Limits */ /* Boundaries and Limits */
fs->n_fatent = nclst + 2; /* Number of FAT entries */ fs->n_fatent = nclst + 2; /* Number of FAT entries */
@ -3383,17 +3444,29 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */
fs->fatbase = bsect + nrsv; /* FAT start sector */ fs->fatbase = bsect + nrsv; /* FAT start sector */
fs->database = bsect + sysect; /* Data start sector */ fs->database = bsect + sysect; /* Data start sector */
if (fmt == FS_FAT32) { if (fmt == FS_FAT32) {
if (ld_word(fs->win + BPB_FSVer32) != 0) return FR_NO_FILESYSTEM; /* (Must be FAT32 revision 0.0) */ if (ld_word(fs->win + BPB_FSVer32) != 0) {
if (fs->n_rootdir != 0) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */ EFSPRINTF("Error: FAT32 - Not a 0.0 revision!");
return FR_NO_FILESYSTEM; /* (Must be FAT32 revision 0.0) */
}
if (fs->n_rootdir != 0) {
EFSPRINTF("Error: FAT32 - Root entry sector is not 0!");
return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */
}
fs->dirbase = ld_dword(fs->win + BPB_RootClus32); /* Root directory start cluster */ fs->dirbase = ld_dword(fs->win + BPB_RootClus32); /* Root directory start cluster */
szbfat = fs->n_fatent * 4; /* (Needed FAT size) */ szbfat = fs->n_fatent * 4; /* (Needed FAT size) */
} else { } else {
if (fs->n_rootdir == 0) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */ if (fs->n_rootdir == 0) {
EFSPRINTF("Error: FAT - Root entry sector is 0!");
return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */
}
fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */ fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */
szbfat = (fmt == FS_FAT16) ? /* (Needed FAT size) */ szbfat = (fmt == FS_FAT16) ? /* (Needed FAT size) */
fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1); fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1);
} }
if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) return FR_NO_FILESYSTEM; /* (BPB_FATSz must not be less than the size needed) */ if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) {
EFSPRINTF("Error: FAT - FAT size is not the required size!");
return FR_NO_FILESYSTEM; /* (BPB_FATSz must not be less than the size needed) */
}
#if !FF_FS_READONLY #if !FF_FS_READONLY
/* Get FSInfo if available */ /* Get FSInfo if available */
@ -3426,7 +3499,7 @@ FRESULT find_volume ( /* FR_OK(0): successful, !=0: any error occurred */
#if FF_USE_LFN == 1 #if FF_USE_LFN == 1
fs->lfnbuf = LfnBuf; /* Static LFN working buffer */ fs->lfnbuf = LfnBuf; /* Static LFN working buffer */
#if FF_FS_EXFAT #if FF_FS_EXFAT
fs->dirbuf = DirBuf; /* Static directory block scratchpad buuffer */ fs->dirbuf = DirBuf; /* Static directory block scratch-pad buffer */
#endif #endif
#endif #endif
#if FF_FS_RPATH != 0 #if FF_FS_RPATH != 0
@ -3504,7 +3577,10 @@ FRESULT f_mount (
/* Get logical drive number */ /* Get logical drive number */
vol = get_ldnumber(&rp); vol = get_ldnumber(&rp);
if (vol < 0) return FR_INVALID_DRIVE; if (vol < 0) {
EFSPRINTF("Error: Invalid drive!");
return FR_INVALID_DRIVE;
}
cfs = FatFs[vol]; /* Pointer to fs object */ cfs = FatFs[vol]; /* Pointer to fs object */
if (cfs) { if (cfs) {
@ -3745,8 +3821,14 @@ FRESULT f_read (
*br = 0; /* Clear read byte counter */ *br = 0; /* Clear read byte counter */
res = validate(&fp->obj, &fs); /* Check validity of the file 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) {
if (!(fp->flag & FA_READ)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ EFSPRINTF("Error: File object Validation!");
LEAVE_FF(fs, res); /* Check validity */
}
if (!(fp->flag & FA_READ)) {
EFSPRINTF("Error: Access denied!");
LEAVE_FF(fs, FR_DENIED); /* Check access mode */
}
remain = fp->obj.objsize - fp->fptr; remain = fp->obj.objsize - fp->fptr;
if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */ if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */
@ -3767,19 +3849,31 @@ FRESULT f_read (
clst = get_fat(&fp->obj, fp->clust); /* Follow cluster chain on the FAT */ clst = get_fat(&fp->obj, fp->clust); /* Follow cluster chain on the FAT */
} }
} }
if (clst < 2) ABORT(fs, FR_INT_ERR); if (clst < 2) {
if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); EFSPRINTF("Error: Cluster status check or Internal error!");
ABORT(fs, FR_INT_ERR);
}
if (clst == 0xFFFFFFFF) {
EFSPRINTF("Error: Disk error (cluster hard error)!");
ABORT(fs, FR_DISK_ERR);
}
fp->clust = clst; /* Update current cluster */ fp->clust = clst; /* Update current cluster */
} }
sect = clst2sect(fs, fp->clust); /* Get current sector */ sect = clst2sect(fs, fp->clust); /* Get current sector */
if (sect == 0) ABORT(fs, FR_INT_ERR); if (sect == 0) {
EFSPRINTF("Error: Get current sector error!");
ABORT(fs, FR_INT_ERR);
}
sect += csect; sect += csect;
cc = btr / SS(fs); /* When remaining bytes >= sector size, */ cc = btr / SS(fs); /* When remaining bytes >= sector size, */
if (cc > 0) { /* Read maximum contiguous sectors directly */ if (cc > 0) { /* Read maximum contiguous sectors directly */
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->pdrv, rbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR); if (disk_read(fs->pdrv, rbuff, sect, cc) != RES_OK) {
EFSPRINTF("Error: Read - Low level disk I/O!");
ABORT(fs, FR_DISK_ERR);
}
#if !FF_FS_READONLY && FF_FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */ #if !FF_FS_READONLY && FF_FS_MINIMIZE <= 2 /* Replace one of the read sectors with cached data if it contains a dirty sector */
#if FF_FS_TINY #if FF_FS_TINY
if (fs->wflag && fs->winsect - sect < cc) { if (fs->wflag && fs->winsect - sect < cc) {
@ -3798,11 +3892,17 @@ FRESULT f_read (
if (fp->sect != sect) { /* Load data sector if not in cache */ if (fp->sect != sect) { /* Load data sector if not in cache */
#if !FF_FS_READONLY #if !FF_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->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) {
EFSPRINTF("Error: Write-back dirty sector cache!");
ABORT(fs, FR_DISK_ERR);
}
fp->flag &= (BYTE)~FA_DIRTY; fp->flag &= (BYTE)~FA_DIRTY;
} }
#endif #endif
if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */ if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) {
EFSPRINTF("Error: Read - Low level disk I/O!\n(fill sector cache)");
ABORT(fs, FR_DISK_ERR); /* Fill sector cache */
}
} }
#endif #endif
fp->sect = sect; fp->sect = sect;
@ -3844,8 +3944,14 @@ FRESULT f_write (
*bw = 0; /* Clear write byte counter */ *bw = 0; /* Clear write byte counter */
res = validate(&fp->obj, &fs); /* Check validity of the file 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) {
if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */ EFSPRINTF("Error: File object Validation!");
LEAVE_FF(fs, res); /* Check validity */
}
if (!(fp->flag & FA_WRITE)) {
EFSPRINTF("Error: Access denied!");
LEAVE_FF(fs, FR_DENIED); /* Check access mode */
}
/* Check fptr wrap-around (file size cannot reach 4 GiB at FAT volume) */ /* Check fptr wrap-around (file size cannot reach 4 GiB at FAT volume) */
if ((!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) && (DWORD)(fp->fptr + btw) < (DWORD)fp->fptr) { if ((!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) && (DWORD)(fp->fptr + btw) < (DWORD)fp->fptr) {
@ -3872,9 +3978,18 @@ FRESULT f_write (
clst = create_chain(&fp->obj, fp->clust); /* Follow or stretch cluster chain on the FAT */ clst = create_chain(&fp->obj, fp->clust); /* Follow or stretch cluster chain on the FAT */
} }
} }
if (clst == 0) break; /* Could not allocate a new cluster (disk full) */ if (clst == 0) {
if (clst == 1) ABORT(fs, FR_INT_ERR); EFSPRINTF("Error: Could not allocate a new cluster\n(disk full or low level disk I/O error)!");
if (clst == 0xFFFFFFFF) ABORT(fs, FR_DISK_ERR); break; /* Could not allocate a new cluster (disk full) */
}
if (clst == 1) {
EFSPRINTF("Error: Cluster status check or Internal error!");
ABORT(fs, FR_INT_ERR);
}
if (clst == 0xFFFFFFFF) {
EFSPRINTF("Error: Disk error (cluster hard error)!");
ABORT(fs, FR_DISK_ERR);
}
fp->clust = clst; /* Update current cluster */ fp->clust = clst; /* Update current cluster */
if (fp->obj.sclust == 0) fp->obj.sclust = clst; /* Set start cluster if the first write */ if (fp->obj.sclust == 0) fp->obj.sclust = clst; /* Set start cluster if the first write */
} }
@ -3882,19 +3997,28 @@ FRESULT f_write (
if (fs->winsect == fp->sect && sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Write-back sector cache */ if (fs->winsect == fp->sect && sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Write-back sector cache */
#else #else
if (fp->flag & FA_DIRTY) { /* Write-back sector cache */ if (fp->flag & FA_DIRTY) { /* Write-back sector cache */
if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) {
EFSPRINTF("Error: Write-back sector cache!");
ABORT(fs, FR_DISK_ERR);
}
fp->flag &= (BYTE)~FA_DIRTY; fp->flag &= (BYTE)~FA_DIRTY;
} }
#endif #endif
sect = clst2sect(fs, fp->clust); /* Get current sector */ sect = clst2sect(fs, fp->clust); /* Get current sector */
if (sect == 0) ABORT(fs, FR_INT_ERR); if (sect == 0) {
EFSPRINTF("Error: Get current sector error!");
ABORT(fs, FR_INT_ERR);
}
sect += csect; sect += csect;
cc = btw / SS(fs); /* When remaining bytes >= sector size, */ cc = btw / SS(fs); /* When remaining bytes >= sector size, */
if (cc > 0) { /* Write maximum contiguous sectors directly */ if (cc > 0) { /* Write maximum contiguous sectors directly */
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->pdrv, wbuff, sect, cc) != RES_OK) ABORT(fs, FR_DISK_ERR); if (disk_write(fs->pdrv, wbuff, sect, cc) != RES_OK) {
EFSPRINTF("Error: Write - Low level disk I/O!");
ABORT(fs, FR_DISK_ERR);
}
#if FF_FS_MINIMIZE <= 2 #if FF_FS_MINIMIZE <= 2
#if FF_FS_TINY #if FF_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 */
@ -3920,6 +4044,7 @@ FRESULT f_write (
if (fp->sect != sect && /* Fill sector cache with file data */ if (fp->sect != sect && /* Fill sector cache with file data */
fp->fptr < fp->obj.objsize && fp->fptr < fp->obj.objsize &&
disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) { disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) {
EFSPRINTF("Error: Read - Low level disk I/O!\n(Could not fill sector cache with file data)");
ABORT(fs, FR_DISK_ERR); ABORT(fs, FR_DISK_ERR);
} }
#endif #endif