提交 ecd84844 编写于 作者: M mazhiyuan

update fatfs to the latest version

上级 574e11f6
# files format check exclude path, please follow the instructions below to modify;
# If you need to exclude an entire folder, add the folder path in dir_path;
# If you need to exclude a file, add the path to the file in file_path.
dir_path:
- diskio.h
- ff.c
- ff.h
- ffconf.h
- ffunicode.c
......@@ -338,3 +338,22 @@ R0.14 (October 14, 2019)
Fixed f_readdir() function returns file names with wrong case conversion. (appeared at R0.12)
Fixed f_mkfs() function can fail to create exFAT volume in the second partition. (appeared at R0.12)
R0.14a (December 5, 2020)
Limited number of recursive calls in f_findnext().
Fixed old floppy disks formatted with MS-DOS 2.x and 3.x cannot be mounted.
Fixed some compiler warnings.
R0.14b (April 17, 2021)
Made FatFs uses standard library <string.h> for copy, compare and search instead of built-in string functions.
Added support for long long integer and floating point to f_printf(). (FF_STRF_LLI and FF_STRF_FP)
Made path name parser ignore the terminating separator to allow "dir/".
Improved the compatibility in Unix style path name feature.
Fixed the file gets dead-locked when f_open() failed with some conditions. (appeared at R0.12a)
Fixed f_mkfs() can create wrong exFAT volume due to a timing dependent error. (appeared at R0.12)
Fixed code page 855 cannot be set by f_setcp().
Fixed some compiler warnings.
FatFs Module Source Files R0.14
FatFs Module Source Files R0.14b
FILES
......
......@@ -10,15 +10,15 @@ extern "C" {
#endif
/* Status of Disk Functions */
typedef BYTE DSTATUS;
typedef BYTE DSTATUS;
/* Results of Disk Functions */
typedef enum {
RES_OK = 0, /* 0: Successful */
RES_ERROR, /* 1: R/W Error */
RES_WRPRT, /* 2: Write Protected */
RES_NOTRDY, /* 3: Not Ready */
RES_PARERR /* 4: Invalid Parameter */
RES_OK = 0, /* 0: Successful */
RES_ERROR, /* 1: R/W Error */
RES_WRPRT, /* 2: Write Protected */
RES_NOTRDY, /* 3: Not Ready */
RES_PARERR /* 4: Invalid Parameter */
} DRESULT;
......@@ -35,40 +35,40 @@ DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
/* Disk Status Bits (DSTATUS) */
#define STA_NOINIT 0x01 /* Drive not initialized */
#define STA_NODISK 0x02 /* No medium in the drive */
#define STA_PROTECT 0x04 /* Write protected */
#define STA_NOINIT 0x01 /* Drive not initialized */
#define STA_NODISK 0x02 /* No medium in the drive */
#define STA_PROTECT 0x04 /* Write protected */
/* Command code for disk_ioctrl fucntion */
/* Generic command (Used by FatFs) */
#define CTRL_SYNC 0 /* Complete pending write process (needed at FF_FS_READONLY == 0) */
#define GET_SECTOR_COUNT 1 /* Get media size (needed at FF_USE_MKFS == 1) */
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */
#define CTRL_SYNC 0 /* Complete pending write process (needed at FF_FS_READONLY == 0) */
#define GET_SECTOR_COUNT 1 /* Get media size (needed at FF_USE_MKFS == 1) */
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_USE_TRIM == 1) */
/* Generic command (Not used by FatFs) */
#define CTRL_POWER 5 /* Get/Set power status */
#define CTRL_LOCK 6 /* Lock/Unlock media removal */
#define CTRL_EJECT 7 /* Eject media */
#define CTRL_FORMAT 8 /* Create physical format on the media */
#define CTRL_POWER 5 /* Get/Set power status */
#define CTRL_LOCK 6 /* Lock/Unlock media removal */
#define CTRL_EJECT 7 /* Eject media */
#define CTRL_FORMAT 8 /* Create physical format on the media */
/* MMC/SDC specific ioctl command */
#define MMC_GET_TYPE 10 /* Get card type */
#define MMC_GET_CSD 11 /* Get CSD */
#define MMC_GET_CID 12 /* Get CID */
#define MMC_GET_OCR 13 /* Get OCR */
#define MMC_GET_SDSTAT 14 /* Get SD status */
#define ISDIO_READ 55 /* Read data form SD iSDIO register */
#define ISDIO_WRITE 56 /* Write data to SD iSDIO register */
#define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */
#define MMC_GET_TYPE 10 /* Get card type */
#define MMC_GET_CSD 11 /* Get CSD */
#define MMC_GET_CID 12 /* Get CID */
#define MMC_GET_OCR 13 /* Get OCR */
#define MMC_GET_SDSTAT 14 /* Get SD status */
#define ISDIO_READ 55 /* Read data form SD iSDIO register */
#define ISDIO_WRITE 56 /* Write data to SD iSDIO register */
#define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */
/* ATA/CF specific ioctl command */
#define ATA_GET_REV 20 /* Get F/W revision */
#define ATA_GET_MODEL 21 /* Get model name */
#define ATA_GET_SN 22 /* Get serial number */
#define ATA_GET_REV 20 /* Get F/W revision */
#define ATA_GET_MODEL 21 /* Get model name */
#define ATA_GET_SN 22 /* Get serial number */
#ifdef __cplusplus
}
......
/*----------------------------------------------------------------------------/
/ FatFs - Generic FAT Filesystem Module R0.14 /
/ FatFs - Generic FAT Filesystem Module R0.14b /
/-----------------------------------------------------------------------------/
/
/ Copyright (C) 2019, ChaN, all right reserved.
/ Copyright (C) 2021, ChaN, all right reserved.
/
/ FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided
......@@ -19,6 +19,7 @@
/----------------------------------------------------------------------------*/
#include <string.h>
#include "ff.h" /* Declarations of FatFs API */
#include "diskio.h" /* Declarations of device I/O functions */
......@@ -29,7 +30,7 @@
---------------------------------------------------------------------------*/
#if FF_DEFINED != 86606 /* Revision ID */
#if FF_DEFINED != 86631 /* Revision ID */
#error Wrong include file (ff.h).
#endif
......@@ -47,6 +48,8 @@
#define IsUpper(c) ((c) >= 'A' && (c) <= 'Z')
#define IsLower(c) ((c) >= 'a' && (c) <= 'z')
#define IsDigit(c) ((c) >= '0' && (c) <= '9')
#define IsSeparator(c) ((c) == '/' || (c) == '\\')
#define IsTerminator(c) ((UINT)(c) < (FF_USE_LFN ? ' ' : '!'))
#define IsSurrogate(c) ((c) >= 0xD800 && (c) <= 0xDFFF)
#define IsSurrogateH(c) ((c) >= 0xD800 && (c) <= 0xDBFF)
#define IsSurrogateL(c) ((c) >= 0xDC00 && (c) <= 0xDFFF)
......@@ -61,7 +64,8 @@
/* Additional file attribute bits for internal use */
#define AM_VOL 0x08 /* Volume label */
#define AM_LFN 0x0F /* LFN entry */
#define AM_MASK 0x3F /* Mask of defined bits */
#define AM_MASK 0x3F /* Mask of defined bits in FAT */
#define AM_MASKX 0x37 /* Mask of defined bits in exFAT */
/* Name status flags in fn[11] */
......@@ -233,7 +237,7 @@
/* Re-entrancy related */
#if FF_FS_REENTRANT
#if FF_USE_LFN == 1
#error Static LFN work area cannot be used at thread-safe configuration
#error Static LFN work area cannot be used in thread-safe configuration
#endif
#define LEAVE_FF(fs, res) { unlock_fs(fs, res); return res; }
#else
......@@ -244,10 +248,10 @@
/* Definitions of logical drive - physical location conversion */
#if FF_MULTI_PARTITION
#define LD2PD(vol) VolToPart[vol].pd /* Get physical drive number */
#define LD2PT(vol) VolToPart[vol].pt /* Get partition index */
#define LD2PT(vol) VolToPart[vol].pt /* Get partition number (0:auto search, 1..:forced partition number) */
#else
#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is associated with the same physical drive number */
#define LD2PT(vol) 0 /* Find first valid partition or in SFD */
#define LD2PT(vol) 0 /* Auto partition search */
#endif
......@@ -556,7 +560,7 @@ static WCHAR LfnBuf[FF_MAX_LFN + 1]; /* LFN working buffer */
/* Code conversion tables */
/*--------------------------------*/
#if FF_CODE_PAGE == 0 /* Run-time code page configuration */
#if FF_CODE_PAGE == 0 /* Run-time code page configuration */
#define CODEPAGE CodePage
static WORD CodePage; /* Current code page */
static const BYTE *ExCvt, *DbcTbl; /* Pointer to current SBCS up-case table and DBCS code range table below */
......@@ -680,53 +684,6 @@ static void st_qword (BYTE* ptr, QWORD val) /* Store an 8-byte word in little-en
/* String functions */
/*-----------------------------------------------------------------------*/
/* Copy memory to memory */
static void mem_cpy (void* dst, const void* src, UINT cnt)
{
BYTE *d = (BYTE*)dst;
const BYTE *s = (const BYTE*)src;
if (cnt != 0) {
do {
*d++ = *s++;
} while (--cnt);
}
}
/* Fill memory block */
static void mem_set (void* dst, int val, UINT cnt)
{
BYTE *d = (BYTE*)dst;
do {
*d++ = (BYTE)val;
} while (--cnt);
}
/* Compare memory block */
static int mem_cmp (const void* dst, const void* src, UINT cnt) /* ZR:same, NZ:different */
{
const BYTE *d = (const BYTE *)dst, *s = (const BYTE *)src;
int r = 0;
do {
r = *d++ - *s++;
} while (--cnt && r == 0);
return r;
}
/* Check if chr is contained in the string */
static int chk_chr (const char* str, int chr) /* NZ:contained, ZR:not contained */
{
while (*str && *str != chr) str++;
return *str;
}
/* Test if the byte is DBC 1st byte */
static int dbc_1st (BYTE c)
{
......@@ -795,18 +752,14 @@ static DWORD tchar2uni ( /* Returns a character in UTF-16 encoding (>=0x10000 on
uc = (BYTE)*p++; /* Get an encoding unit */
if (uc & 0x80) { /* Multiple byte code? */
if ((uc & 0xE0) == 0xC0) { /* 2-byte sequence? */
if ((uc & 0xE0) == 0xC0) { /* 2-byte sequence? */
uc &= 0x1F; nf = 1;
} else {
if ((uc & 0xF0) == 0xE0) { /* 3-byte sequence? */
uc &= 0x0F; nf = 2;
} else {
if ((uc & 0xF8) == 0xF0) { /* 4-byte sequence? */
uc &= 0x07; nf = 3;
} else { /* Wrong sequence */
return 0xFFFFFFFF;
}
}
} else if ((uc & 0xF0) == 0xE0) { /* 3-byte sequence? */
uc &= 0x0F; nf = 2;
} else if ((uc & 0xF8) == 0xF0) { /* 4-byte sequence? */
uc &= 0x07; nf = 3;
} else { /* Wrong sequence */
return 0xFFFFFFFF;
}
do { /* Get trailing bytes */
b = (BYTE)*p++;
......@@ -844,8 +797,8 @@ static DWORD tchar2uni ( /* Returns a character in UTF-16 encoding (>=0x10000 on
}
/* Output a TCHAR string in defined API encoding */
static BYTE put_utf ( /* Returns number of encoding units written (0:buffer overflow or wrong encoding) */
/* Store a Unicode char in defined API encoding */
static UINT put_utf ( /* Returns number of encoding units written (0:buffer overflow or wrong encoding) */
DWORD chr, /* UTF-16 encoded character (Surrogate pair if >=0x10000) */
TCHAR* buf, /* Output buffer */
UINT szb /* Size of the buffer */
......@@ -1011,7 +964,7 @@ static UINT inc_lock ( /* Increment object open counter and returns its index (0
&& Files[i].ofs == dp->dptr) break;
}
if (i == FF_FS_LOCK) { /* Not opened. Register it as new. */
if (i == FF_FS_LOCK) { /* Not opened. Register it as new. */
for (i = 0; i < FF_FS_LOCK && Files[i].fs; i++) ;
if (i == FF_FS_LOCK) return 0; /* No free entry to register (int err) */
Files[i].fs = dp->obj.fs;
......@@ -1038,13 +991,13 @@ static FRESULT dec_lock ( /* Decrement object open counter */
if (--i < FF_FS_LOCK) { /* Index number origin from 0 */
n = Files[i].ctr;
if (n == 0x100) n = 0; /* If write mode open, delete the entry */
if (n > 0) n--; /* Decrement read mode open count */
if (n == 0x100) n = 0; /* If write mode open, delete the entry */
if (n > 0) n--; /* Decrement read mode open count */
Files[i].ctr = n;
if (n == 0) Files[i].fs = 0; /* Delete the entry if open count gets zero */
res = FR_OK;
} else {
res = FR_INT_ERR; /* Invalid index nunber */
res = FR_INT_ERR; /* Invalid index nunber */
}
return res;
}
......@@ -1133,14 +1086,13 @@ static FRESULT sync_fs ( /* Returns FR_OK or FR_DISK_ERR */
if (res == FR_OK) {
if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) { /* FAT32: Update FSInfo sector if needed */
/* Create FSInfo structure */
mem_set(fs->win, 0, sizeof fs->win);
st_word(fs->win + BS_55AA, 0xAA55);
st_dword(fs->win + FSI_LeadSig, 0x41615252);
st_dword(fs->win + FSI_StrucSig, 0x61417272);
st_dword(fs->win + FSI_Free_Count, fs->free_clst);
st_dword(fs->win + FSI_Nxt_Free, fs->last_clst);
/* Write it into the FSInfo sector */
fs->winsect = fs->volbase + 1;
memset(fs->win, 0, sizeof fs->win);
st_word(fs->win + BS_55AA, 0xAA55); /* Boot signature */
st_dword(fs->win + FSI_LeadSig, 0x41615252); /* Leading signature */
st_dword(fs->win + FSI_StrucSig, 0x61417272); /* Structure signature */
st_dword(fs->win + FSI_Free_Count, fs->free_clst); /* Number of free clusters */
st_dword(fs->win + FSI_Nxt_Free, fs->last_clst); /* Last allocated culuster */
fs->winsect = fs->volbase + 1; /* Write it into the FSInfo sector (Next to VBR) */
disk_write(fs->pdrv, fs->win, fs->winsect, 1);
fs->fsi_flag = 0;
}
......@@ -1173,7 +1125,7 @@ static LBA_t clst2sect ( /* !=0:Sector number, 0:Failed (invalid cluster#) */
/*-----------------------------------------------------------------------*/
/* FAT access - Read value of a FAT entry */
/* FAT access - Read value of an FAT entry */
/*-----------------------------------------------------------------------*/
static DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x7FFFFFFF:Cluster status */
......@@ -1235,7 +1187,8 @@ static DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x7FFFFFF
break;
}
}
/* go to default */
val = 1; /* Internal error */
break;
#endif
default:
val = 1; /* Internal error */
......@@ -1250,7 +1203,7 @@ static DWORD get_fat ( /* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x7FFFFFF
#if !FF_FS_READONLY
/*-----------------------------------------------------------------------*/
/* FAT access - Change value of a FAT entry */
/* FAT access - Change value of an FAT entry */
/*-----------------------------------------------------------------------*/
static FRESULT put_fat ( /* FR_OK(0):succeeded, !=0:error */
......@@ -1266,12 +1219,12 @@ static FRESULT put_fat ( /* FR_OK(0):succeeded, !=0:error */
if (clst >= 2 && clst < fs->n_fatent) { /* Check if in valid range */
switch (fs->fs_type) {
case FS_FAT12 :
case FS_FAT12:
bc = (UINT)clst; bc += bc / 2; /* bc: byte offset of the entry */
res = move_window(fs, fs->fatbase + (bc / SS(fs)));
if (res != FR_OK) break;
p = fs->win + bc++ % SS(fs);
*p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val; /* Update 1st byte */
*p = (clst & 1) ? ((*p & 0x0F) | ((BYTE)val << 4)) : (BYTE)val; /* Update 1st byte */
fs->wflag = 1;
res = move_window(fs, fs->fatbase + (bc / SS(fs)));
if (res != FR_OK) break;
......@@ -1280,16 +1233,16 @@ static FRESULT put_fat ( /* FR_OK(0):succeeded, !=0:error */
fs->wflag = 1;
break;
case FS_FAT16 :
case FS_FAT16:
res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 2)));
if (res != FR_OK) break;
st_word(fs->win + clst * 2 % SS(fs), (WORD)val); /* Simple WORD array */
fs->wflag = 1;
break;
case FS_FAT32 :
case FS_FAT32:
#if FF_FS_EXFAT
case FS_EXFAT :
case FS_EXFAT:
#endif
res = move_window(fs, fs->fatbase + (clst / (SS(fs) / 4)));
if (res != FR_OK) break;
......@@ -1684,12 +1637,12 @@ static FRESULT dir_clear ( /* Returns FR_OK or FR_DISK_ERR */
if (sync_window(fs) != FR_OK) return FR_DISK_ERR; /* Flush disk access window */
sect = clst2sect(fs, clst); /* Top of the cluster */
fs->winsect = sect; /* Set window to top of the cluster */
mem_set(fs->win, 0, sizeof fs->win); /* Clear window buffer */
memset(fs->win, 0, sizeof fs->win); /* Clear window buffer */
#if FF_USE_LFN == 3 /* Quick table clear by using multi-secter write */
/* Allocate a temporary buffer */
for (szb = ((DWORD)fs->csize * SS(fs) >= MAX_MALLOC) ? MAX_MALLOC : fs->csize * SS(fs), ibuf = 0; szb > SS(fs) && (ibuf = ff_memalloc(szb)) == 0; szb /= 2) ;
if (szb > SS(fs)) { /* Buffer allocated? */
mem_set(ibuf, 0, szb);
memset(ibuf, 0, szb);
szb /= SS(fs); /* Bytes -> Sectors */
for (n = 0; n < fs->csize && disk_write(fs->pdrv, ibuf, sect + n, szb) == RES_OK; n += szb) ; /* Fill the cluster with 0 */
ff_memfree(ibuf);
......@@ -1821,7 +1774,7 @@ static FRESULT dir_next ( /* FR_OK(0):succeeded, FR_NO_FILE:End of table, FR_DEN
static FRESULT dir_alloc ( /* FR_OK(0):succeeded, !=0:error */
DIR* dp, /* Pointer to the directory object */
UINT nent /* Number of contiguous entries to allocate */
UINT n_ent /* Number of contiguous entries to allocate */
)
{
FRESULT res;
......@@ -1836,16 +1789,16 @@ static FRESULT dir_alloc ( /* FR_OK(0):succeeded, !=0:error */
res = move_window(fs, dp->sect);
if (res != FR_OK) break;
#if FF_FS_EXFAT
if ((fs->fs_type == FS_EXFAT) ? (int)((dp->dir[XDIR_Type] & 0x80) == 0) : (int)(dp->dir[DIR_Name] == DDEM || dp->dir[DIR_Name] == 0)) {
if ((fs->fs_type == FS_EXFAT) ? (int)((dp->dir[XDIR_Type] & 0x80) == 0) : (int)(dp->dir[DIR_Name] == DDEM || dp->dir[DIR_Name] == 0)) { /* Is the entry free? */
#else
if (dp->dir[DIR_Name] == DDEM || dp->dir[DIR_Name] == 0) {
if (dp->dir[DIR_Name] == DDEM || dp->dir[DIR_Name] == 0) { /* Is the entry free? */
#endif
if (++n == nent) break; /* A block of contiguous free entries is found */
if (++n == n_ent) break; /* Is a block of contiguous free entries found? */
} else {
n = 0; /* Not a blank entry. Restart to search */
n = 0; /* Not a free entry, restart to search */
}
res = dir_next(dp, 1);
} while (res == FR_OK); /* Next entry with table stretch enabled */
res = dir_next(dp, 1); /* Next entry with table stretch enabled */
} while (res == FR_OK);
}
if (res == FR_NO_FILE) res = FR_DENIED; /* No directory entry to allocate */
......@@ -1993,7 +1946,7 @@ static void put_lfn (
do {
if (wc != 0xFFFF) wc = lfn[i++]; /* Get an effective character */
st_word(dir + LfnOfs[s], wc); /* Put it */
if (wc == 0) wc = 0xFFFF; /* Padding characters for following items */
if (wc == 0) wc = 0xFFFF; /* Padding characters for following items */
} while (++s < 13);
if (wc == 0xFFFF || !lfn[i]) ord |= LLEF; /* Last LFN part is the start of LFN sequence */
dir[LDIR_Ord] = ord; /* Set the LFN order */
......@@ -2011,7 +1964,7 @@ static void put_lfn (
static void gen_numname (
BYTE* dst, /* Pointer to the buffer to store numbered SFN */
const BYTE* src, /* Pointer to SFN */
const BYTE* src, /* Pointer to SFN in directory form */
const WCHAR* lfn, /* Pointer to LFN */
UINT seq /* Sequence number */
)
......@@ -2022,7 +1975,7 @@ static void gen_numname (
DWORD sreg;
mem_cpy(dst, src, 11);
memcpy(dst, src, 11); /* Prepare the SFN to be modified */
if (seq > 5) { /* In case of many collisions, generate a hash number instead of sequential number */
sreg = seq;
......@@ -2037,24 +1990,23 @@ static void gen_numname (
seq = (UINT)sreg;
}
/* itoa (hexdecimal) */
/* Make suffix (~ + hexdecimal) */
i = 7;
do {
c = (BYTE)((seq % 16) + '0');
c = (BYTE)((seq % 16) + '0'); seq /= 16;
if (c > '9') c += 7;
ns[i--] = c;
seq /= 16;
} while (seq);
} while (i && seq);
ns[i] = '~';
/* Append the number to the SFN body */
for (j = 0; j < i && dst[j] != ' '; j++) {
if (dbc_1st(dst[j])) {
/* Append the suffix to the SFN body */
for (j = 0; j < i && dst[j] != ' '; j++) { /* Find the offset to append */
if (dbc_1st(dst[j])) { /* To avoid DBC break up */
if (j == i - 1) break;
j++;
}
}
do {
do { /* Append the suffix */
dst[j++] = (i < 8) ? ns[i++] : ' ';
} while (j < 8);
}
......@@ -2139,47 +2091,6 @@ static DWORD xsum32 ( /* Returns 32-bit checksum */
#endif
#if FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2
/*------------------------------------------------------*/
/* exFAT: Get object information from a directory block */
/*------------------------------------------------------*/
static void get_xfileinfo (
BYTE* dirb, /* Pointer to the direcotry entry block 85+C0+C1s */
FILINFO* fno /* Buffer to store the extracted file information */
)
{
WCHAR wc, hs;
UINT di, si, nc;
/* Get file name from the entry block */
si = SZDIRE * 2; /* 1st C1 entry */
nc = 0; hs = 0; di = 0;
while (nc < dirb[XDIR_NumName]) {
if (si >= MAXDIRB(FF_MAX_LFN)) { di = 0; break; } /* Truncated directory block? */
if ((si % SZDIRE) == 0) si += 2; /* Skip entry type field */
wc = ld_word(dirb + si); si += 2; nc++; /* Get a character */
if (hs == 0 && IsSurrogate(wc)) { /* Is it a surrogate? */
hs = wc; continue; /* Get low surrogate */
}
wc = put_utf((DWORD)hs << 16 | wc, &fno->fname[di], FF_LFN_BUF - di); /* Store it in API encoding */
if (wc == 0) { di = 0; break; } /* Buffer overflow or wrong encoding? */
di += wc;
hs = 0;
}
if (hs != 0) di = 0; /* Broken surrogate pair? */
if (di == 0) fno->fname[di++] = '?'; /* Inaccessible object name? */
fno->fname[di] = 0; /* Terminate the name */
fno->altname[0] = 0; /* exFAT does not support SFN */
fno->fattrib = dirb[XDIR_Attr]; /* Attribute */
fno->fsize = (fno->fattrib & AM_DIR) ? 0 : ld_qword(dirb + XDIR_FileSize); /* Size */
fno->ftime = ld_word(dirb + XDIR_ModTime + 0); /* Time */
fno->fdate = ld_word(dirb + XDIR_ModTime + 2); /* Date */
}
#endif /* FF_FS_MINIMIZE <= 1 || FF_FS_RPATH >= 2 */
/*-----------------------------------*/
/* exFAT: Get a directry entry block */
......@@ -2191,28 +2102,28 @@ static FRESULT load_xdir ( /* FR_INT_ERR: invalid entry block */
{
FRESULT res;
UINT i, sz_ent;
BYTE* dirb = dp->obj.fs->dirbuf; /* Pointer to the on-memory direcotry entry block 85+C0+C1s */
BYTE *dirb = dp->obj.fs->dirbuf; /* Pointer to the on-memory direcotry entry block 85+C0+C1s */
/* Load file-directory entry */
/* Load file directory entry */
res = move_window(dp->obj.fs, dp->sect);
if (res != FR_OK) return res;
if (dp->dir[XDIR_Type] != ET_FILEDIR) return FR_INT_ERR; /* Invalid order */
mem_cpy(dirb + 0 * SZDIRE, dp->dir, SZDIRE);
memcpy(dirb + 0 * SZDIRE, dp->dir, SZDIRE);
sz_ent = (dirb[XDIR_NumSec] + 1) * SZDIRE;
if (sz_ent < 3 * SZDIRE || sz_ent > 19 * SZDIRE) return FR_INT_ERR;
/* Load stream-extension entry */
/* Load stream extension entry */
res = dir_next(dp, 0);
if (res == FR_NO_FILE) res = FR_INT_ERR; /* It cannot be */
if (res != FR_OK) return res;
res = move_window(dp->obj.fs, dp->sect);
if (res != FR_OK) return res;
if (dp->dir[XDIR_Type] != ET_STREAM) return FR_INT_ERR; /* Invalid order */
mem_cpy(dirb + 1 * SZDIRE, dp->dir, SZDIRE);
memcpy(dirb + 1 * SZDIRE, dp->dir, SZDIRE);
if (MAXDIRB(dirb[XDIR_NumName]) > sz_ent) return FR_INT_ERR;
/* Load file-name entries */
/* Load file name entries */
i = 2 * SZDIRE; /* Name offset to load */
do {
res = dir_next(dp, 0);
......@@ -2221,7 +2132,7 @@ static FRESULT load_xdir ( /* FR_INT_ERR: invalid entry block */
res = move_window(dp->obj.fs, dp->sect);
if (res != FR_OK) return res;
if (dp->dir[XDIR_Type] != ET_FILENAME) return FR_INT_ERR; /* Invalid order */
if (i < MAXDIRB(FF_MAX_LFN)) mem_cpy(dirb + i, dp->dir, SZDIRE);
if (i < MAXDIRB(FF_MAX_LFN)) memcpy(dirb + i, dp->dir, SZDIRE);
} while ((i += SZDIRE) < sz_ent);
/* Sanity check (do it for only accessible object) */
......@@ -2289,7 +2200,7 @@ static FRESULT store_xdir (
{
FRESULT res;
UINT nent;
BYTE* dirb = dp->obj.fs->dirbuf; /* Pointer to the direcotry entry block 85+C0+C1s */
BYTE *dirb = dp->obj.fs->dirbuf; /* Pointer to the direcotry entry block 85+C0+C1s */
/* Create set sum */
st_word(dirb + XDIR_SetSum, xdir_sum(dirb));
......@@ -2300,7 +2211,7 @@ static FRESULT store_xdir (
while (res == FR_OK) {
res = move_window(dp->obj.fs, dp->sect);
if (res != FR_OK) break;
mem_cpy(dp->dir, dirb, SZDIRE);
memcpy(dp->dir, dirb, SZDIRE);
dp->obj.fs->wflag = 1;
if (--nent == 0) break;
dirb += SZDIRE;
......@@ -2326,7 +2237,7 @@ static void create_xdir (
/* Create file-directory and stream-extension entry */
mem_set(dirb, 0, 2 * SZDIRE);
memset(dirb, 0, 2 * SZDIRE);
dirb[0 * SZDIRE + XDIR_Type] = ET_FILEDIR;
dirb[1 * SZDIRE + XDIR_Type] = ET_STREAM;
......@@ -2337,7 +2248,7 @@ static void create_xdir (
dirb[i++] = ET_FILENAME; dirb[i++] = 0;
do { /* Fill name field */
if (wc != 0 && (wc = lfn[nlen]) != 0) nlen++; /* Get a character if exist */
st_word(dirb + i, wc); /* Store it */
st_word(dirb + i, wc); /* Store it */
i += 2;
} while (i % SZDIRE != 0);
nc1++;
......@@ -2402,17 +2313,17 @@ static FRESULT dir_read (
if (b == DDEM || b == '.' || (int)((attr & ~AM_ARC) == AM_VOL) != vol) { /* An entry without valid data */
ord = 0xFF;
} else {
if (attr == AM_LFN) { /* An LFN entry is found */
if (b & LLEF) { /* Is it start of an LFN sequence? */
if (attr == AM_LFN) { /* An LFN entry is found */
if (b & LLEF) { /* Is it start of an LFN sequence? */
sum = dp->dir[LDIR_Chksum];
b &= (BYTE)~LLEF; ord = b;
dp->blk_ofs = dp->dptr;
}
/* Check LFN validity and capture it */
ord = (b == ord && sum == dp->dir[LDIR_Chksum] && pick_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF;
} else { /* An SFN entry is found */
} else { /* An SFN entry is found */
if (ord != 0 || sum != sum_sfn(dp->dir)) { /* Is there a valid LFN? */
dp->blk_ofs = 0xFFFFFFFF; /* It has no LFN. */
dp->blk_ofs = 0xFFFFFFFF; /* It has no LFN. */
}
break;
}
......@@ -2460,7 +2371,7 @@ static FRESULT dir_find ( /* FR_OK(0):succeeded, !=0:error */
while ((res = DIR_READ_FILE(dp)) == FR_OK) { /* Read an item */
#if FF_MAX_LFN < 255
if (fs->dirbuf[XDIR_NumName] > FF_MAX_LFN) continue; /* Skip comparison if inaccessible object name */
if (fs->dirbuf[XDIR_NumName] > FF_MAX_LFN) continue; /* Skip comparison if inaccessible object name */
#endif
if (ld_word(fs->dirbuf + XDIR_NameHash) != hash) continue; /* Skip comparison if hash mismatched */
for (nc = fs->dirbuf[XDIR_NumName], di = SZDIRE * 2, ni = 0; nc; nc--, di += 2, ni++) { /* Compare the name */
......@@ -2498,13 +2409,13 @@ static FRESULT dir_find ( /* FR_OK(0):succeeded, !=0:error */
}
} else { /* An SFN entry is found */
if (ord == 0 && sum == sum_sfn(dp->dir)) break; /* LFN matched? */
if (!(dp->fn[NSFLAG] & NS_LOSS) && !mem_cmp(dp->dir, dp->fn, 11)) break; /* SFN matched? */
if (!(dp->fn[NSFLAG] & NS_LOSS) && !memcmp(dp->dir, dp->fn, 11)) break; /* SFN matched? */
ord = 0xFF; dp->blk_ofs = 0xFFFFFFFF; /* Reset LFN sequence */
}
}
#else /* Non LFN configuration */
dp->obj.attr = dp->dir[DIR_Attr] & AM_MASK;
if (!(dp->dir[DIR_Attr] & AM_VOL) && !mem_cmp(dp->dir, dp->fn, 11)) break; /* Is it a valid entry? */
if (!(dp->dir[DIR_Attr] & AM_VOL) && !memcmp(dp->dir, dp->fn, 11)) break; /* Is it a valid entry? */
#endif
res = dir_next(dp, 0); /* Next entry */
} while (res == FR_OK);
......@@ -2527,19 +2438,19 @@ static FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too
FRESULT res;
FATFS *fs = dp->obj.fs;
#if FF_USE_LFN /* LFN configuration */
UINT n, nlen, nent;
UINT n, len, n_ent;
BYTE sn[12], sum;
if (dp->fn[NSFLAG] & (NS_DOT | NS_NONAME)) return FR_INVALID_NAME; /* Check name validity */
for (nlen = 0; fs->lfnbuf[nlen]; nlen++) ; /* Get lfn length */
for (len = 0; fs->lfnbuf[len]; len++) ; /* Get lfn length */
#if FF_FS_EXFAT
if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
nent = (nlen + 14) / 15 + 2; /* Number of entries to allocate (85+C0+C1s) */
res = dir_alloc(dp, nent); /* Allocate directory entries */
n_ent = (len + 14) / 15 + 2; /* Number of entries to allocate (85+C0+C1s) */
res = dir_alloc(dp, n_ent); /* Allocate directory entries */
if (res != FR_OK) return res;
dp->blk_ofs = dp->dptr - SZDIRE * (nent - 1); /* Set the allocated entry block offset */
dp->blk_ofs = dp->dptr - SZDIRE * (n_ent - 1); /* Set the allocated entry block offset */
if (dp->obj.stat & 4) { /* Has the directory been stretched by new allocation? */
dp->obj.stat &= ~4;
......@@ -2552,10 +2463,10 @@ static FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too
res = load_obj_xdir(&dj, &dp->obj); /* Load the object status */
if (res != FR_OK) return res;
dp->obj.objsize += (DWORD)fs->csize * SS(fs); /* Increase the directory size by cluster size */
dp->obj.objsize += (DWORD)fs->csize * SS(fs); /* Increase the directory size by cluster size */
st_qword(fs->dirbuf + XDIR_FileSize, dp->obj.objsize);
st_qword(fs->dirbuf + XDIR_ValidFileSize, dp->obj.objsize);
fs->dirbuf[XDIR_GenFlags] = dp->obj.stat | 1; /* Update the allocation status */
fs->dirbuf[XDIR_GenFlags] = dp->obj.stat | 1; /* Update the allocation status */
res = store_xdir(&dj); /* Store the object status */
if (res != FR_OK) return res;
}
......@@ -2566,7 +2477,7 @@ static FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too
}
#endif
/* On the FAT/FAT32 volume */
mem_cpy(sn, dp->fn, 12);
memcpy(sn, dp->fn, 12);
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 */
for (n = 1; n < 100; n++) {
......@@ -2580,19 +2491,19 @@ static FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too
}
/* Create an SFN with/without LFNs. */
nent = (sn[NSFLAG] & NS_LFN) ? (nlen + 12) / 13 + 1 : 1; /* Number of entries to allocate */
res = dir_alloc(dp, nent); /* Allocate entries */
if (res == FR_OK && --nent) { /* Set LFN entry if needed */
res = dir_sdi(dp, dp->dptr - nent * SZDIRE);
n_ent = (sn[NSFLAG] & NS_LFN) ? (len + 12) / 13 + 1 : 1; /* Number of entries to allocate */
res = dir_alloc(dp, n_ent); /* Allocate entries */
if (res == FR_OK && --n_ent) { /* Set LFN entry if needed */
res = dir_sdi(dp, dp->dptr - n_ent * SZDIRE);
if (res == FR_OK) {
sum = sum_sfn(dp->fn); /* Checksum value of the SFN tied to the LFN */
do { /* Store LFN entries in bottom first */
res = move_window(fs, dp->sect);
if (res != FR_OK) break;
put_lfn(fs->lfnbuf, dp->dir, (BYTE)nent, sum);
put_lfn(fs->lfnbuf, dp->dir, (BYTE)n_ent, sum);
fs->wflag = 1;
res = dir_next(dp, 0); /* Next entry */
} while (res == FR_OK && --nent);
} while (res == FR_OK && --n_ent);
}
}
......@@ -2605,8 +2516,8 @@ static FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too
if (res == FR_OK) {
res = move_window(fs, dp->sect);
if (res == FR_OK) {
mem_set(dp->dir, 0, SZDIRE); /* Clean the entry */
mem_cpy(dp->dir + DIR_Name, dp->fn, 11); /* Put SFN */
memset(dp->dir, 0, SZDIRE); /* Clean the entry */
memcpy(dp->dir + DIR_Name, dp->fn, 11); /* Put SFN */
#if FF_USE_LFN
dp->dir[DIR_NTres] = dp->fn[NSFLAG] & (NS_BODY | NS_EXT); /* Put NT flag */
#endif
......@@ -2642,7 +2553,7 @@ static FRESULT dir_remove ( /* FR_OK:Succeeded, FR_DISK_ERR:A disk error */
if (res != FR_OK) break;
if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
dp->dir[XDIR_Type] &= 0x7F; /* Clear the entry InUse flag. */
} else { /* On the FAT/FAT32 volume */
} else { /* On the FAT/FAT32 volume */
dp->dir[DIR_Name] = DDEM; /* Mark the entry 'deleted'. */
}
fs->wflag = 1;
......@@ -2682,6 +2593,7 @@ static void get_fileinfo (
BYTE lcf;
WCHAR wc, hs;
FATFS *fs = dp->obj.fs;
UINT nw;
#else
TCHAR c;
#endif
......@@ -2692,22 +2604,47 @@ static void get_fileinfo (
#if FF_USE_LFN /* LFN configuration */
#if FF_FS_EXFAT
if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
get_xfileinfo(fs->dirbuf, fno);
if (fs->fs_type == FS_EXFAT) { /* exFAT volume */
UINT nc = 0;
si = SZDIRE * 2; di = 0; /* 1st C1 entry in the entry block */
hs = 0;
while (nc < fs->dirbuf[XDIR_NumName]) {
if (si >= MAXDIRB(FF_MAX_LFN)) { di = 0; break; } /* Truncated directory block? */
if ((si % SZDIRE) == 0) si += 2; /* Skip entry type field */
wc = ld_word(fs->dirbuf + si); si += 2; nc++; /* Get a character */
if (hs == 0 && IsSurrogate(wc)) { /* Is it a surrogate? */
hs = wc; continue; /* Get low surrogate */
}
nw = put_utf((DWORD)hs << 16 | wc, &fno->fname[di], FF_LFN_BUF - di); /* Store it in API encoding */
if (nw == 0) { di = 0; break; } /* Buffer overflow or wrong char? */
di += nw;
hs = 0;
}
if (hs != 0) di = 0; /* Broken surrogate pair? */
if (di == 0) fno->fname[di++] = '?'; /* Inaccessible object name? */
fno->fname[di] = 0; /* Terminate the name */
fno->altname[0] = 0; /* exFAT does not support SFN */
fno->fattrib = fs->dirbuf[XDIR_Attr] & AM_MASKX; /* Attribute */
fno->fsize = (fno->fattrib & AM_DIR) ? 0 : ld_qword(fs->dirbuf + XDIR_FileSize); /* Size */
fno->ftime = ld_word(fs->dirbuf + XDIR_ModTime + 0); /* Time */
fno->fdate = ld_word(fs->dirbuf + XDIR_ModTime + 2); /* Date */
return;
} else
#endif
{ /* On the FAT/FAT32 volume */
{ /* FAT/FAT32 volume */
if (dp->blk_ofs != 0xFFFFFFFF) { /* Get LFN if available */
si = di = hs = 0;
si = di = 0;
hs = 0;
while (fs->lfnbuf[si] != 0) {
wc = fs->lfnbuf[si++]; /* Get an LFN character (UTF-16) */
if (hs == 0 && IsSurrogate(wc)) { /* Is it a surrogate? */
hs = wc; continue; /* Get low surrogate */
}
wc = put_utf((DWORD)hs << 16 | wc, &fno->fname[di], FF_LFN_BUF - di); /* Store it in UTF-16 or UTF-8 encoding */
if (wc == 0) { di = 0; break; } /* Invalid char or buffer overflow? */
di += wc;
nw = put_utf((DWORD)hs << 16 | wc, &fno->fname[di], FF_LFN_BUF - di); /* Store it in API encoding */
if (nw == 0) { di = 0; break; } /* Buffer overflow or wrong char? */
di += nw;
hs = 0;
}
if (hs != 0) di = 0; /* Broken surrogate pair? */
......@@ -2727,9 +2664,9 @@ static void get_fileinfo (
}
wc = ff_oem2uni(wc, CODEPAGE); /* ANSI/OEM -> Unicode */
if (wc == 0) { di = 0; break; } /* Wrong char in the current code page? */
wc = put_utf(wc, &fno->altname[di], FF_SFN_BUF - di); /* Store it in Unicode */
if (wc == 0) { di = 0; break; } /* Buffer overflow? */
di += wc;
nw = put_utf(wc, &fno->altname[di], FF_SFN_BUF - di); /* Store it in API encoding */
if (nw == 0) { di = 0; break; } /* Buffer overflow? */
di += nw;
#else /* ANSI/OEM output */
fno->altname[di++] = (TCHAR)wc; /* Store it without any conversion */
#endif
......@@ -2760,10 +2697,10 @@ static void get_fileinfo (
if (si == 9) fno->fname[di++] = '.';/* Insert a . if extension is exist */
fno->fname[di++] = c;
}
fno->fname[di] = 0;
fno->fname[di] = 0; /* Terminate the SFN */
#endif
fno->fattrib = dp->dir[DIR_Attr]; /* Attribute */
fno->fattrib = dp->dir[DIR_Attr] & AM_MASK; /* Attribute */
fno->fsize = ld_dword(dp->dir + DIR_FileSize); /* Size */
fno->ftime = ld_word(dp->dir + DIR_ModTime + 0); /* Time */
fno->fdate = ld_word(dp->dir + DIR_ModTime + 2); /* Date */
......@@ -2778,7 +2715,10 @@ static void get_fileinfo (
/* Pattern matching */
/*-----------------------------------------------------------------------*/
static DWORD get_achar ( /* Get a character and advances ptr */
#define FIND_RECURS 4 /* Maximum number of wildcard terms in the pattern to limit recursion */
static DWORD get_achar ( /* Get a character and advance ptr */
const TCHAR** ptr /* Pointer to pointer to the ANSI/OEM or Unicode string */
)
{
......@@ -2809,41 +2749,43 @@ static DWORD get_achar ( /* Get a character and advances ptr */
}
static int pattern_matching ( /* 0:not matched, 1:matched */
static int pattern_match ( /* 0:mismatched, 1:matched */
const TCHAR* pat, /* Matching pattern */
const TCHAR* nam, /* String to be tested */
int skip, /* Number of pre-skip chars (number of ?s) */
int inf /* Infinite search (* specified) */
UINT skip, /* Number of pre-skip chars (number of ?s, b8:infinite (* specified)) */
UINT recur /* Recursion count */
)
{
const TCHAR *pp, *np;
DWORD pc, nc;
int nm, nx;
const TCHAR *pptr, *nptr;
DWORD pchr, nchr;
UINT sk;
while (skip--) { /* Pre-skip name chars */
while ((skip & 0xFF) != 0) { /* Pre-skip name chars */
if (!get_achar(&nam)) return 0; /* Branch mismatched if less name chars */
skip--;
}
if (*pat == 0 && inf) return 1; /* (short circuit) */
if (*pat == 0 && skip) return 1; /* Matched? (short circuit) */
do {
pp = pat; np = nam; /* Top of pattern and name to match */
pptr = pat; nptr = nam; /* Top of pattern and name to match */
for (;;) {
if (*pp == '?' || *pp == '*') { /* Wildcard? */
nm = nx = 0;
do { /* Analyze the wildcard block */
if (*pp++ == '?') nm++; else nx = 1;
} while (*pp == '?' || *pp == '*');
if (pattern_matching(pp, np, nm, nx)) return 1; /* Test new branch (recurs upto number of wildcard blocks in the pattern) */
nc = *np; break; /* Branch mismatched */
}
pc = get_achar(&pp); /* Get a pattern char */
nc = get_achar(&np); /* Get a name char */
if (pc != nc) break; /* Branch mismatched? */
if (pc == 0) return 1; /* Branch matched? (matched at end of both strings) */
if (*pptr == '?' || *pptr == '*') { /* Wildcard term? */
if (recur == 0) return 0; /* Too many wildcard terms? */
sk = 0;
do { /* Analyze the wildcard term */
if (*pptr++ == '?') sk++; else sk |= 0x100;
} while (*pptr == '?' || *pptr == '*');
if (pattern_match(pptr, nptr, sk, recur - 1)) return 1; /* Test new branch (recursive call) */
nchr = *nptr; break; /* Branch mismatched */
}
pchr = get_achar(&pptr); /* Get a pattern char */
nchr = get_achar(&nptr); /* Get a name char */
if (pchr != nchr) break; /* Branch mismatched? */
if (pchr == 0) return 1; /* Branch matched? (matched at end of both strings) */
}
get_achar(&nam); /* nam++ */
} while (inf && nc); /* Retry until end of name if infinite search is specified */
} while (skip && nchr); /* Retry until end of name if infinite search is specified */
return 0;
}
......@@ -2876,16 +2818,17 @@ static FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not cr
if (uc == 0xFFFFFFFF) return FR_INVALID_NAME; /* Invalid code or UTF decode error */
if (uc >= 0x10000) lfn[di++] = (WCHAR)(uc >> 16); /* Store high surrogate if needed */
wc = (WCHAR)uc;
if (wc < ' ' || wc == '/' || wc == '\\') break; /* Break if end of the path or a separator is found */
if (wc < 0x80 && chk_chr("\"*:<>\?|\x7F", wc)) return FR_INVALID_NAME; /* Reject illegal characters for LFN */
if (wc < ' ' || IsSeparator(wc)) break; /* Break if end of the path or a separator is found */
if (wc < 0x80 && strchr("*:<>|\"\?\x7F", (int)wc)) return FR_INVALID_NAME; /* Reject illegal characters for LFN */
if (di >= FF_MAX_LFN) return FR_INVALID_NAME; /* Reject too long name */
lfn[di++] = wc; /* Store the Unicode character */
lfn[di++] = wc; /* Store the Unicode character */
}
if (wc < ' ') { /* End of path? */
cf = NS_LAST; /* Set last segment flag */
} else {
cf = 0; /* Next segment follows */
while (*p == '/' || *p == '\\') p++; /* Skip duplicated separators if exist */
if (wc < ' ') { /* Stopped at end of the path? */
cf = NS_LAST; /* Last segment */
} else { /* Stopped at a separator */
while (IsSeparator(*p)) p++; /* Skip duplicated separators if exist */
cf = 0; /* Next segment may follow */
if (IsTerminator(*p)) cf = NS_LAST; /* Ignore terminating separator */
}
*path = p; /* Return pointer to the next segment */
......@@ -2893,14 +2836,14 @@ static FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not cr
if ((di == 1 && lfn[di - 1] == '.') ||
(di == 2 && lfn[di - 1] == '.' && lfn[di - 2] == '.')) { /* Is this segment a dot name? */
lfn[di] = 0;
for (i = 0; i < 11; i++) { /* Create dot name for SFN entry */
for (i = 0; i < 11; i++) { /* Create dot name for SFN entry */
dp->fn[i] = (i < di) ? '.' : ' ';
}
dp->fn[i] = cf | NS_DOT; /* This is a dot entry */
dp->fn[i] = cf | NS_DOT; /* This is a dot entry */
return FR_OK;
}
#endif
while (di) { /* Snip off trailing spaces and dots if exist */
while (di) { /* Snip off trailing spaces and dots if exist */
wc = lfn[di - 1];
if (wc != ' ' && wc != '.') break;
di--;
......@@ -2913,7 +2856,7 @@ static FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not cr
if (si > 0 || lfn[si] == '.') cf |= NS_LOSS | NS_LFN; /* Is there any leading space or dot? */
while (di > 0 && lfn[di - 1] != '.') di--; /* Find last dot (di<=si: no extension) */
mem_set(dp->fn, ' ', 11);
memset(dp->fn, ' ', 11);
i = b = 0; ni = 8;
for (;;) {
wc = lfn[si++]; /* Get an LFN character */
......@@ -2934,20 +2877,20 @@ static FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not cr
continue;
}
if (wc >= 0x80) { /* Is this a non-ASCII character? */
if (wc >= 0x80) { /* Is this an extended character? */
cf |= NS_LFN; /* LFN entry needs to be created */
#if FF_CODE_PAGE == 0
if (ExCvt) { /* At SBCS */
if (ExCvt) { /* In SBCS cfg */
wc = ff_uni2oem(wc, CODEPAGE); /* Unicode ==> ANSI/OEM code */
if (wc & 0x80) wc = ExCvt[wc & 0x7F]; /* Convert extended character to upper (SBCS) */
} else { /* At DBCS */
wc = ff_uni2oem(ff_wtoupper(wc), CODEPAGE); /* Unicode ==> Upper convert ==> ANSI/OEM code */
} else { /* In DBCS cfg */
wc = ff_uni2oem(ff_wtoupper(wc), CODEPAGE); /* Unicode ==> Up-convert ==> ANSI/OEM code */
}
#elif FF_CODE_PAGE < 900 /* SBCS cfg */
#elif FF_CODE_PAGE < 900 /* In SBCS cfg */
wc = ff_uni2oem(wc, CODEPAGE); /* Unicode ==> ANSI/OEM code */
if (wc & 0x80) wc = ExCvt[wc & 0x7F]; /* Convert extended character to upper (SBCS) */
#else /* DBCS cfg */
wc = ff_uni2oem(ff_wtoupper(wc), CODEPAGE); /* Unicode ==> Upper convert ==> ANSI/OEM code */
#else /* In DBCS cfg */
wc = ff_uni2oem(ff_wtoupper(wc), CODEPAGE); /* Unicode ==> Up-convert ==> ANSI/OEM code */
#endif
}
......@@ -2958,7 +2901,7 @@ static FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not cr
}
dp->fn[i++] = (BYTE)(wc >> 8); /* Put 1st byte */
} else { /* SBC */
if (wc == 0 || chk_chr("+,;=[]", wc)) { /* Replace illegal characters for SFN if needed */
if (wc == 0 || strchr("+,;=[]", (int)wc)) { /* Replace illegal characters for SFN */
wc = '_'; cf |= NS_LOSS | NS_LFN;/* Lossy conversion */
} else {
if (IsUpper(wc)) { /* ASCII upper case? */
......@@ -2993,7 +2936,7 @@ static FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not cr
/* Create file name in directory form */
p = *path; sfn = dp->fn;
mem_set(sfn, ' ', 11);
memset(sfn, ' ', 11);
si = i = 0; ni = 8;
#if FF_FS_RPATH != 0
if (p[si] == '.') { /* Is this a dot entry? */
......@@ -3002,8 +2945,8 @@ static FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not cr
if (c != '.' || si >= 3) break;
sfn[i++] = c;
}
if (c != '/' && c != '\\' && c > ' ') return FR_INVALID_NAME;
*path = p + si; /* Return pointer to the next segment */
if (!IsSeparator(c) && c > ' ') return FR_INVALID_NAME;
*path = p + si; /* Return pointer to the next segment */
sfn[NSFLAG] = (c <= ' ') ? NS_LAST | NS_DOT : NS_DOT; /* Set last segment flag if end of the path */
return FR_OK;
}
......@@ -3011,8 +2954,8 @@ static FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not cr
for (;;) {
c = (BYTE)p[si++]; /* Get a byte */
if (c <= ' ') break; /* Break if end of the path name */
if (c == '/' || c == '\\') { /* Break if a separator is found */
while (p[si] == '/' || p[si] == '\\') si++; /* Skip duplicated separator if exist */
if (IsSeparator(c)) { /* Break if a separator is found */
while (IsSeparator(p[si])) si++; /* Skip duplicated separator if exist */
break;
}
if (c == '.' || i >= ni) { /* End of body or field overflow? */
......@@ -3035,16 +2978,16 @@ static FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not cr
sfn[i++] = c;
sfn[i++] = d;
} else { /* SBC */
if (chk_chr("\"*+,:;<=>\?[]|\x7F", c)) return FR_INVALID_NAME; /* Reject illegal chrs for SFN */
if (strchr("*+,:;<=>[]|\"\?\x7F", (int)c)) return FR_INVALID_NAME; /* Reject illegal chrs for SFN */
if (IsLower(c)) c -= 0x20; /* To upper */
sfn[i++] = c;
}
}
*path = p + si; /* Return pointer to the next segment */
*path = &p[si]; /* Return pointer to the next segment */
if (i == 0) return FR_INVALID_NAME; /* Reject nul string */
if (sfn[0] == DDEM) sfn[0] = RDDEM; /* If the first character collides with DDEM, replace it with RDDEM */
sfn[NSFLAG] = (c <= ' ') ? NS_LAST : 0; /* Set last segment flag if end of the path */
sfn[NSFLAG] = (c <= ' ' || p[si] <= ' ') ? NS_LAST : 0; /* Set last segment flag if end of the path */
return FR_OK;
#endif /* FF_USE_LFN */
......@@ -3068,13 +3011,13 @@ static FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */
#if FF_FS_RPATH != 0
if (*path != '/' && *path != '\\') { /* Without heading separator */
dp->obj.sclust = fs->cdir; /* Start from current directory */
if (!IsSeparator(*path) && (FF_STR_VOLUME_ID != 2 || !IsTerminator(*path))) { /* Without heading separator */
dp->obj.sclust = fs->cdir; /* Start at the current directory */
} else
#endif
{ /* With heading separator */
while (*path == '/' || *path == '\\') path++; /* Strip heading separator */
dp->obj.sclust = 0; /* Start from root directory */
while (IsSeparator(*path)) path++; /* Strip separators */
dp->obj.sclust = 0; /* Start from the root directory */
}
#if FF_FS_EXFAT
dp->obj.n_frag = 0; /* Invalidate last fragment counter of the object */
......@@ -3115,13 +3058,13 @@ static FRESULT follow_path ( /* FR_OK(0): successful, !=0: error code */
}
break;
}
if (ns & NS_LAST) break; /* Last segment matched. Function completed. */
if (ns & NS_LAST) break; /* Last segment matched. Function completed. */
/* Get into the sub-directory */
if (!(dp->obj.attr & AM_DIR)) { /* It is not a sub-directory and cannot follow */
if (!(dp->obj.attr & AM_DIR)) { /* It is not a sub-directory and cannot follow */
res = FR_NO_PATH; break;
}
#if FF_FS_EXFAT
if (fs->fs_type == FS_EXFAT) { /* Save containing directory information for next dir */
if (fs->fs_type == FS_EXFAT) { /* Save containing directory information for next dir */
dp->obj.c_scl = dp->obj.sclust;
dp->obj.c_size = ((DWORD)dp->obj.objsize & 0xFFFFFF00) | dp->obj.stat;
dp->obj.c_ofs = dp->blk_ofs;
......@@ -3150,7 +3093,8 @@ static int get_ldnumber ( /* Returns logical drive number (-1:invalid drive numb
{
const TCHAR *tp, *tt;
TCHAR tc;
int i, vol = -1;
int i;
int vol = -1;
#if FF_STR_VOLUME_ID /* Find string volume ID */
const char *sp;
char c;
......@@ -3158,7 +3102,7 @@ static int get_ldnumber ( /* Returns logical drive number (-1:invalid drive numb
tt = tp = *path;
if (!tp) return vol; /* Invalid path name? */
do tc = *tt++; while ((UINT)tc >= (FF_USE_LFN ? ' ' : '!') && tc != ':'); /* Find a colon in the path */
do tc = *tt++; while (!IsTerminator(tc) && tc != ':'); /* Find a colon in the path */
if (tc == ':') { /* DOS/Windows style volume ID? */
i = FF_VOLUMES;
......@@ -3185,21 +3129,22 @@ static int get_ldnumber ( /* Returns logical drive number (-1:invalid drive numb
return vol;
}
#if FF_STR_VOLUME_ID == 2 /* Unix style volume ID is enabled */
if (*tp == '/') {
if (*tp == '/') { /* Is there a volume ID? */
while (*(tp + 1) == '/') tp++; /* Skip duplicated separator */
i = 0;
do {
sp = VolumeStr[i]; tp = *path; /* This string volume ID and path name */
tt = tp; sp = VolumeStr[i]; /* Path name and this string volume ID */
do { /* Compare the volume ID with path name */
c = *sp++; tc = *(++tp);
c = *sp++; tc = *(++tt);
if (IsLower(c)) c -= 0x20;
if (IsLower(tc)) tc -= 0x20;
} while (c && (TCHAR)c == tc);
} while ((c || (tc != '/' && (UINT)tc >= (FF_USE_LFN ? ' ' : '!'))) && ++i < FF_VOLUMES); /* Repeat for each ID until pattern match */
} while ((c || (tc != '/' && !IsTerminator(tc))) && ++i < FF_VOLUMES); /* Repeat for each ID until pattern match */
if (i < FF_VOLUMES) { /* If a volume ID is found, get the drive number and strip it */
vol = i; /* Drive number */
*path = tp; /* Snip the drive prefix off */
return vol;
*path = tt; /* Snip the drive prefix off */
}
return vol;
}
#endif
/* No drive prefix is found */
......@@ -3248,7 +3193,7 @@ static int test_gpt_header ( /* 0:Invalid, 1:Valid */
DWORD bcc;
if (mem_cmp(gpth + GPTH_Sign, "EFI PART" "\0\0\1\0" "\x5C\0\0", 16)) return 0; /* Check sign, version (1.0) and length (92) */
if (memcmp(gpth + GPTH_Sign, "EFI PART" "\0\0\1\0" "\x5C\0\0", 16)) return 0; /* Check sign, version (1.0) and length (92) */
for (i = 0, bcc = 0xFFFFFFFF; i < 92; i++) { /* Check header BCC */
bcc = crc32(bcc, i - GPTH_Bcc < 4 ? 0 : gpth[i]);
}
......@@ -3290,7 +3235,7 @@ static DWORD make_rand (
/* Check what the sector is */
static UINT check_fs ( /* 0:FAT VBR, 1:exFAT VBR, 2:Not FAT and valid BS, 3:Not FAT and invalid BS, 4:Disk error */
static UINT check_fs ( /* 0:FAT/FAT32 VBR, 1:exFAT VBR, 2:Not FAT and valid BS, 3:Not FAT and invalid BS, 4:Disk error */
FATFS* fs, /* Filesystem object */
LBA_t sect /* Sector to load and check if it is an FAT-VBR or not */
)
......@@ -3303,21 +3248,24 @@ static UINT check_fs ( /* 0:FAT VBR, 1:exFAT VBR, 2:Not FAT and valid BS, 3:Not
if (move_window(fs, sect) != FR_OK) return 4; /* Load the boot sector */
sign = ld_word(fs->win + BS_55AA);
#if FF_FS_EXFAT
if (sign == 0xAA55 && !mem_cmp(fs->win + BS_JmpBoot, "\xEB\x76\x90" "EXFAT ", 11)) return 1; /* It is an exFAT VBR */
if (sign == 0xAA55 && !memcmp(fs->win + BS_JmpBoot, "\xEB\x76\x90" "EXFAT ", 11)) return 1; /* It is an exFAT VBR */
#endif
b = fs->win[BS_JmpBoot];
if (b == 0xEB || b == 0xE9 || b == 0xE8) { /* Valid JumpBoot code? (short jump, near jump or near call) */
if (sign == 0xAA55 && !mem_cmp(fs->win + BS_FilSysType32, "FAT32 ", 8)) return 0; /* It is an FAT32 VBR */
/* FAT volumes formatted with early MS-DOS lack boot signature and FAT string, so that we need to identify the FAT VBR without them. */
if (sign == 0xAA55 && !memcmp(fs->win + BS_FilSysType32, "FAT32 ", 8)) {
return 0; /* It is an FAT32 VBR */
}
/* FAT volumes formatted with early MS-DOS lack BS_55AA and BS_FilSysType, so FAT VBR needs to be identified without them. */
w = ld_word(fs->win + BPB_BytsPerSec);
if ((w & (w - 1)) == 0 && w >= FF_MIN_SS && w <= FF_MAX_SS) { /* Properness of sector size */
b = fs->win[BPB_SecPerClus];
if (b != 0 && (b & (b - 1)) == 0 /* Properness of cluster size */
&& (fs->win[BPB_NumFATs] == 1 || fs->win[BPB_NumFATs] == 2) /* Properness of number of FATs */
&& ld_word(fs->win + BPB_RootEntCnt) != 0 /* Properness of root entry count */
&& ld_word(fs->win + BPB_FATSz16) != 0) { /* Properness of FAT size */
return 0; /* Sector can be presumed an FAT VBR */
}
b = fs->win[BPB_SecPerClus];
if ((w & (w - 1)) == 0 && w >= FF_MIN_SS && w <= FF_MAX_SS /* Properness of sector size (512-4096 and 2^n) */
&& b != 0 && (b & (b - 1)) == 0 /* Properness of cluster size (2^n) */
&& ld_word(fs->win + BPB_RsvdSecCnt) != 0 /* Properness of reserved sectors (MNBZ) */
&& (UINT)fs->win[BPB_NumFATs] - 1 <= 1 /* Properness of FATs (1 or 2) */
&& ld_word(fs->win + BPB_RootEntCnt) != 0 /* Properness of root dir entries (MNBZ) */
&& (ld_word(fs->win + BPB_TotSec16) >= 128 || ld_dword(fs->win + BPB_TotSec32) >= 0x10000) /* Properness of volume sectors (>=128) */
&& ld_word(fs->win + BPB_FATSz16) != 0) { /* Properness of FAT size (MNBZ) */
return 0; /* It can be presumed an FAT VBR */
}
}
return sign == 0xAA55 ? 2 : 3; /* Not an FAT VBR (valid or invalid BS) */
......@@ -3336,8 +3284,8 @@ static UINT find_volume ( /* Returns BS status found in the hosting drive */
DWORD mbr_pt[4];
fmt = check_fs(fs, 0); /* Load sector 0 and check if it is an FAT VBR as SFD */
if (fmt != 2 && (fmt >= 3 || part == 0)) return fmt; /* Returns if it is a FAT VBR as auto scan, not a BS or disk error */
fmt = check_fs(fs, 0); /* Load sector 0 and check if it is an FAT VBR as SFD format */
if (fmt != 2 && (fmt >= 3 || part == 0)) return fmt; /* Returns if it is an FAT VBR as auto scan, not a BS or disk error */
/* Sector 0 is not an FAT VBR or forced partition number wants a partition */
......@@ -3353,7 +3301,7 @@ static UINT find_volume ( /* Returns BS status found in the hosting drive */
for (v_ent = i = 0; i < n_ent; i++) { /* Find FAT partition */
if (move_window(fs, pt_lba + i * SZ_GPTE / SS(fs)) != FR_OK) return 4; /* PT sector */
ofs = i * SZ_GPTE % SS(fs); /* Offset in the sector */
if (!mem_cmp(fs->win + ofs + GPTE_PtGuid, GUID_MS_Basic, 16)) { /* MS basic data partition? */
if (!memcmp(fs->win + ofs + GPTE_PtGuid, GUID_MS_Basic, 16)) { /* MS basic data partition? */
v_ent++;
fmt = check_fs(fs, ld_qword(fs->win + ofs + GPTE_FstLba)); /* Load VBR and check status */
if (part == 0 && fmt <= 1) return fmt; /* Auto search (valid FAT volume found first) */
......@@ -3421,7 +3369,7 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */
}
/* The filesystem object is not valid. */
/* Following code attempts to mount the volume. (find a FAT volume, analyze the BPB and initialize the filesystem object) */
/* Following code attempts to mount the volume. (find an FAT volume, analyze the BPB and initialize the filesystem object) */
fs->fs_type = 0; /* Clear the filesystem object */
fs->pdrv = LD2PD(vol); /* Volume hosting physical drive */
......@@ -3441,7 +3389,7 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */
fmt = find_volume(fs, LD2PT(vol));
if (fmt == 4) return FR_DISK_ERR; /* An error occured in the disk I/O layer */
if (fmt >= 2) return FR_NO_FILESYSTEM; /* No FAT volume is found */
bsect = fs->winsect; /* Volume location */
bsect = fs->winsect; /* Volume offset */
/* An FAT volume is found (bsect). Following code initializes the filesystem object */
......@@ -3459,8 +3407,8 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */
return FR_NO_FILESYSTEM;
}
maxlba = ld_qword(fs->win + BPB_TotSecEx) + bsect; /* Last LBA + 1 of the volume */
if (!FF_LBA64 && maxlba >= 0x100000000) return FR_NO_FILESYSTEM; /* (It cannot be handled in 32-bit LBA) */
maxlba = ld_qword(fs->win + BPB_TotSecEx) + bsect; /* Last LBA of the volume + 1 */
if (!FF_LBA64 && maxlba >= 0x100000000) return FR_NO_FILESYSTEM; /* (It cannot be accessed in 32-bit LBA) */
fs->fsize = ld_dword(fs->win + BPB_FatSzEx); /* Number of sectors per FAT */
......@@ -3468,7 +3416,7 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */
if (fs->n_fats != 1) return FR_NO_FILESYSTEM; /* (Supports only 1 FAT) */
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) return FR_NO_FILESYSTEM; /* (Must be 1..32768 sectors) */
nclst = ld_dword(fs->win + BPB_NumClusEx); /* Number of clusters */
if (nclst > MAX_EXFAT) return FR_NO_FILESYSTEM; /* (Too many clusters) */
......@@ -3489,11 +3437,11 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */
if (move_window(fs, clst2sect(fs, (DWORD)fs->dirbase) + so) != FR_OK) return FR_DISK_ERR;
so++;
}
if (fs->win[i] == ET_BITMAP) break; /* Is it a bitmap entry? */
if (fs->win[i] == ET_BITMAP) break; /* Is it a bitmap entry? */
i = (i + SZDIRE) % SS(fs); /* Next entry */
}
bcl = ld_dword(fs->win + i + 20); /* Bitmap cluster */
if (bcl < 2 || bcl >= fs->n_fatent) return FR_NO_FILESYSTEM;
bcl = ld_dword(fs->win + i + 20); /* Bitmap cluster */
if (bcl < 2 || bcl >= fs->n_fatent) return FR_NO_FILESYSTEM; /* (Wrong cluster#) */
fs->bitbase = fs->database + fs->csize * (bcl - 2); /* Bitmap sector */
for (;;) { /* Check if bitmap is contiguous */
if (move_window(fs, fs->fatbase + bcl / (SS(fs) / 4)) != FR_OK) return FR_DISK_ERR;
......@@ -3655,9 +3603,9 @@ static FRESULT validate ( /* Returns FR_OK or FR_INVALID_OBJECT */
/*-----------------------------------------------------------------------*/
FRESULT f_mount (
FATFS* fs, /* Pointer to the filesystem object (NULL:unmount)*/
FATFS* fs, /* Pointer to the filesystem object to be registered (NULL:unmount)*/
const TCHAR* path, /* Logical drive number to be mounted/unmounted */
BYTE opt /* Mode option 0:Do not mount (delayed mount), 1:Mount immediately */
BYTE opt /* Mount option: 0=Do not mount (delayed mount), 1=Mount immediately */
)
{
FATFS *cfs;
......@@ -3705,14 +3653,14 @@ FRESULT f_mount (
FRESULT f_open (
FIL* fp, /* Pointer to the blank file object */
const TCHAR* path, /* Pointer to the file name */
BYTE mode /* Access mode and file open mode flags */
BYTE mode /* Access mode and open mode flags */
)
{
FRESULT res;
DIR dj;
FATFS *fs;
#if !FF_FS_READONLY
DWORD cl, bcs, clst;
DWORD cl, bcs, clst, tm;
LBA_t sc;
FSIZE_t ofs;
#endif
......@@ -3765,8 +3713,8 @@ FRESULT f_open (
fp->obj.fs = fs;
init_alloc_info(fs, &fp->obj);
/* Set directory entry block initial state */
mem_set(fs->dirbuf + 2, 0, 30); /* Clear 85 entry except for NumSec */
mem_set(fs->dirbuf + 38, 0, 26); /* Clear C0 entry except for NumName and NameHash */
memset(fs->dirbuf + 2, 0, 30); /* Clear 85 entry except for NumSec */
memset(fs->dirbuf + 38, 0, 26); /* Clear C0 entry except for NumName and NameHash */
fs->dirbuf[XDIR_Attr] = AM_ARC;
st_dword(fs->dirbuf + XDIR_CrtTime, GET_FATTIME());
fs->dirbuf[XDIR_GenFlags] = 1;
......@@ -3779,8 +3727,10 @@ FRESULT f_open (
#endif
{
/* Set directory entry initial state */
tm = GET_FATTIME(); /* Set created time */
st_dword(dj.dir + DIR_CrtTime, tm);
st_dword(dj.dir + DIR_ModTime, tm);
cl = ld_clust(fs, dj.dir); /* Get current cluster chain */
st_dword(dj.dir + DIR_CrtTime, GET_FATTIME()); /* Set created time */
dj.dir[DIR_Attr] = AM_ARC; /* Reset attribute */
st_clust(fs, dj.dir, 0); /* Reset file allocation info */
st_dword(dj.dir + DIR_FileSize, 0);
......@@ -3842,17 +3792,17 @@ FRESULT f_open (
fp->obj.objsize = ld_dword(dj.dir + DIR_FileSize);
}
#if FF_USE_FASTSEEK
fp->cltbl = 0; /* Disable fast seek mode */
fp->cltbl = 0; /* Disable fast seek mode */
#endif
fp->obj.fs = fs; /* Validate the file object */
fp->obj.fs = fs; /* Validate the file object */
fp->obj.id = fs->id;
fp->flag = mode; /* Set file access mode */
fp->err = 0; /* Clear error flag */
fp->sect = 0; /* Invalidate current data sector */
fp->fptr = 0; /* Set file pointer top of the file */
fp->flag = mode; /* Set file access mode */
fp->err = 0; /* Clear error flag */
fp->sect = 0; /* Invalidate current data sector */
fp->fptr = 0; /* Set file pointer top of the file */
#if !FF_FS_READONLY
#if !FF_FS_TINY
mem_set(fp->buf, 0, sizeof fp->buf); /* Clear sector buffer */
memset(fp->buf, 0, sizeof fp->buf); /* Clear sector buffer */
#endif
if ((mode & FA_SEEKEND) && fp->obj.objsize > 0) { /* Seek to end of file if FA_OPEN_APPEND is specified */
fp->fptr = fp->obj.objsize; /* Offset to seek */
......@@ -3875,6 +3825,9 @@ FRESULT f_open (
#endif
}
}
#if FF_FS_LOCK != 0
if (res != FR_OK) dec_lock(fp->obj.lockid); /* Decrement file open counter if seek failed */
#endif
}
#endif
}
......@@ -3895,10 +3848,10 @@ FRESULT f_open (
/*-----------------------------------------------------------------------*/
FRESULT f_read (
FIL* fp, /* Pointer to the file object */
void* buff, /* Pointer to data buffer */
FIL* fp, /* Open file to be read */
void* buff, /* Data buffer to store the read data */
UINT btr, /* Number of bytes to read */
UINT* br /* Pointer to number of bytes read */
UINT* br /* Number of bytes read */
)
{
FRESULT res;
......@@ -3917,8 +3870,7 @@ FRESULT f_read (
remain = fp->obj.objsize - fp->fptr;
if (btr > remain) btr = (UINT)remain; /* Truncate btr by remaining bytes */
for ( ; btr; /* Repeat until btr bytes read */
btr -= rcnt, *br += rcnt, rbuff += rcnt, fp->fptr += rcnt) {
for ( ; btr > 0; btr -= rcnt, *br += rcnt, rbuff += rcnt, fp->fptr += rcnt) { /* Repeat until btr bytes read */
if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */
csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1)); /* Sector offset in the cluster */
if (csect == 0) { /* On the cluster boundary? */
......@@ -3950,11 +3902,11 @@ FRESULT f_read (
#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 (fs->wflag && fs->winsect - sect < cc) {
mem_cpy(rbuff + ((fs->winsect - sect) * SS(fs)), fs->win, SS(fs));
memcpy(rbuff + ((fs->winsect - sect) * SS(fs)), fs->win, SS(fs));
}
#else
if ((fp->flag & FA_DIRTY) && fp->sect - sect < cc) {
mem_cpy(rbuff + ((fp->sect - sect) * SS(fs)), fp->buf, SS(fs));
memcpy(rbuff + ((fp->sect - sect) * SS(fs)), fp->buf, SS(fs));
}
#endif
#endif
......@@ -3978,9 +3930,9 @@ FRESULT f_read (
if (rcnt > btr) rcnt = btr; /* Clip it by btr if needed */
#if FF_FS_TINY
if (move_window(fs, fp->sect) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Move sector window */
mem_cpy(rbuff, fs->win + fp->fptr % SS(fs), rcnt); /* Extract partial sector */
memcpy(rbuff, fs->win + fp->fptr % SS(fs), rcnt); /* Extract partial sector */
#else
mem_cpy(rbuff, fp->buf + fp->fptr % SS(fs), rcnt); /* Extract partial sector */
memcpy(rbuff, fp->buf + fp->fptr % SS(fs), rcnt); /* Extract partial sector */
#endif
}
......@@ -3996,10 +3948,10 @@ FRESULT f_read (
/*-----------------------------------------------------------------------*/
FRESULT f_write (
FIL* fp, /* Pointer to the file object */
const void* buff, /* Pointer to the data to be written */
FIL* fp, /* Open file to be written */
const void* buff, /* Data to be written */
UINT btw, /* Number of bytes to write */
UINT* bw /* Pointer to number of bytes written */
UINT* bw /* Number of bytes written */
)
{
FRESULT res;
......@@ -4020,8 +3972,7 @@ FRESULT f_write (
btw = (UINT)(0xFFFFFFFF - (DWORD)fp->fptr);
}
for ( ; btw; /* Repeat until all data written */
btw -= wcnt, *bw += wcnt, wbuff += wcnt, fp->fptr += wcnt, fp->obj.objsize = (fp->fptr > fp->obj.objsize) ? fp->fptr : fp->obj.objsize) {
for ( ; btw > 0; btw -= wcnt, *bw += wcnt, wbuff += wcnt, fp->fptr += wcnt, fp->obj.objsize = (fp->fptr > fp->obj.objsize) ? fp->fptr : fp->obj.objsize) { /* Repeat until all data written */
if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */
csect = (UINT)(fp->fptr / SS(fs)) & (fs->csize - 1); /* Sector offset in the cluster */
if (csect == 0) { /* On the cluster boundary? */
......@@ -4066,12 +4017,12 @@ FRESULT f_write (
#if FF_FS_MINIMIZE <= 2
#if FF_FS_TINY
if (fs->winsect - sect < cc) { /* Refill sector cache if it gets invalidated by the direct write */
mem_cpy(fs->win, wbuff + ((fs->winsect - sect) * SS(fs)), SS(fs));
memcpy(fs->win, wbuff + ((fs->winsect - sect) * SS(fs)), SS(fs));
fs->wflag = 0;
}
#else
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));
memcpy(fp->buf, wbuff + ((fp->sect - sect) * SS(fs)), SS(fs));
fp->flag &= (BYTE)~FA_DIRTY;
}
#endif
......@@ -4097,10 +4048,10 @@ FRESULT f_write (
if (wcnt > btw) wcnt = btw; /* Clip it by btw if needed */
#if FF_FS_TINY
if (move_window(fs, fp->sect) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Move sector window */
mem_cpy(fs->win + fp->fptr % SS(fs), wbuff, wcnt); /* Fit data to the sector */
memcpy(fs->win + fp->fptr % SS(fs), wbuff, wcnt); /* Fit data to the sector */
fs->wflag = 1;
#else
mem_cpy(fp->buf + fp->fptr % SS(fs), wbuff, wcnt); /* Fit data to the sector */
memcpy(fp->buf + fp->fptr % SS(fs), wbuff, wcnt); /* Fit data to the sector */
fp->flag |= FA_DIRTY;
#endif
}
......@@ -4118,7 +4069,7 @@ FRESULT f_write (
/*-----------------------------------------------------------------------*/
FRESULT f_sync (
FIL* fp /* Pointer to the file object */
FIL* fp /* Open file to be synced */
)
{
FRESULT res;
......@@ -4199,7 +4150,7 @@ FRESULT f_sync (
/*-----------------------------------------------------------------------*/
FRESULT f_close (
FIL* fp /* Pointer to the file object to be closed */
FIL* fp /* Open file to be closed */
)
{
FRESULT res;
......@@ -4300,7 +4251,7 @@ FRESULT f_chdir (
}
FREE_NAMBUF();
if (res == FR_NO_FILE) res = FR_NO_PATH;
#if FF_STR_VOLUME_ID == 2 /* Also current drive is changed at Unix style volume ID */
#if FF_STR_VOLUME_ID == 2 /* Also current drive is changed if in Unix style volume ID */
if (res == FR_OK) {
for (i = FF_VOLUMES - 1; i && fs != FatFs[i]; i--) ; /* Set current drive */
CurrVol = (BYTE)i;
......@@ -4424,7 +4375,8 @@ FRESULT f_lseek (
LBA_t nsect;
FSIZE_t ifptr;
#if FF_USE_FASTSEEK
DWORD cl, pcl, ncl, tcl, tlen, ulen, *tbl;
DWORD cl, pcl, ncl, tcl, tlen, ulen;
DWORD *tbl;
LBA_t dsc;
#endif
......@@ -4736,9 +4688,9 @@ FRESULT f_findnext (
for (;;) {
res = f_readdir(dp, fno); /* Get a directory item */
if (res != FR_OK || !fno || !fno->fname[0]) break; /* Terminate if any error or end of directory */
if (pattern_matching(dp->pat, fno->fname, 0, 0)) break; /* Test for the file name */
if (pattern_match(dp->pat, fno->fname, 0, FIND_RECURS)) break; /* Test for the file name */
#if FF_USE_LFN && FF_USE_FIND == 2
if (pattern_matching(dp->pat, fno->altname, 0, 0)) break; /* Test for alternative name if exist */
if (pattern_match(dp->pat, fno->altname, 0, FIND_RECURS)) break; /* Test for alternative name if exist */
#endif
}
return res;
......@@ -4886,9 +4838,11 @@ FRESULT f_getfree (
} while (--clst);
}
}
*nclst = nfree; /* Return the free clusters */
fs->free_clst = nfree; /* Now free_clst is valid */
fs->fsi_flag |= 1; /* FAT32: FSInfo is to be updated */
if (res == FR_OK) { /* Update parameters if succeeded */
*nclst = nfree; /* Return the free clusters */
fs->free_clst = nfree; /* Now free_clst is valid */
fs->fsi_flag |= 1; /* FAT32: FSInfo is to be updated */
}
}
}
......@@ -4999,12 +4953,12 @@ FRESULT f_unlink (
}
if (dj.obj.attr & AM_DIR) { /* Is it a sub-directory? */
#if FF_FS_RPATH != 0
if (dclst == fs->cdir) { /* Is it the current directory? */
if (dclst == fs->cdir) { /* Is it the current directory? */
res = FR_DENIED;
} else
#endif
{
sdj.obj.fs = fs; /* Open the sub-directory */
sdj.obj.fs = fs; /* Open the sub-directory */
sdj.obj.sclust = dclst;
#if FF_FS_EXFAT
if (fs->fs_type == FS_EXFAT) {
......@@ -5079,12 +5033,12 @@ FRESULT f_mkdir (
res = dir_clear(fs, dcl); /* Clean up the new table */
if (res == FR_OK) {
if (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) { /* Create dot entries (FAT only) */
mem_set(fs->win + DIR_Name, ' ', 11); /* Create "." entry */
memset(fs->win + DIR_Name, ' ', 11); /* Create "." entry */
fs->win[DIR_Name] = '.';
fs->win[DIR_Attr] = AM_DIR;
st_dword(fs->win + DIR_ModTime, tm);
st_clust(fs, fs->win, dcl);
mem_cpy(fs->win + SZDIRE, fs->win, SZDIRE); /* Create ".." entry */
memcpy(fs->win + SZDIRE, fs->win, SZDIRE); /* Create ".." entry */
fs->win[SZDIRE + 1] = '.'; pcl = dj.obj.sclust;
st_clust(fs, fs->win + SZDIRE, pcl);
fs->wflag = 1;
......@@ -5148,21 +5102,21 @@ FRESULT f_rename (
if (res == FR_OK) {
djo.obj.fs = fs;
INIT_NAMBUF(fs);
res = follow_path(&djo, path_old); /* Check old object */
res = follow_path(&djo, path_old); /* Check old object */
if (res == FR_OK && (djo.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME; /* Check validity of name */
#if FF_FS_LOCK != 0
if (res == FR_OK) {
res = chk_lock(&djo, 2);
}
#endif
if (res == FR_OK) { /* Object to be renamed is found */
if (res == FR_OK) { /* Object to be renamed is found */
#if FF_FS_EXFAT
if (fs->fs_type == FS_EXFAT) { /* At exFAT volume */
BYTE nf, nn;
WORD nh;
mem_cpy(buf, fs->dirbuf, SZDIRE * 2); /* Save 85+C0 entry of old object */
mem_cpy(&djn, &djo, sizeof djo);
memcpy(buf, fs->dirbuf, SZDIRE * 2); /* Save 85+C0 entry of old object */
memcpy(&djn, &djo, sizeof djo);
res = follow_path(&djn, path_new); /* Make sure if new object name is not 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;
......@@ -5172,7 +5126,7 @@ FRESULT f_rename (
if (res == FR_OK) {
nf = fs->dirbuf[XDIR_NumSec]; nn = fs->dirbuf[XDIR_NumName];
nh = ld_word(fs->dirbuf + XDIR_NameHash);
mem_cpy(fs->dirbuf, buf, SZDIRE * 2); /* Restore 85+C0 entry */
memcpy(fs->dirbuf, buf, SZDIRE * 2); /* Restore 85+C0 entry */
fs->dirbuf[XDIR_NumSec] = nf; fs->dirbuf[XDIR_NumName] = nn;
st_word(fs->dirbuf + XDIR_NameHash, nh);
if (!(fs->dirbuf[XDIR_Attr] & AM_DIR)) fs->dirbuf[XDIR_Attr] |= AM_ARC; /* Set archive attribute if it is a file */
......@@ -5183,8 +5137,8 @@ FRESULT f_rename (
} else
#endif
{ /* At FAT/FAT32 volume */
mem_cpy(buf, djo.dir, SZDIRE); /* Save directory entry of the object */
mem_cpy(&djn, &djo, sizeof (DIR)); /* Duplicate the directory object */
memcpy(buf, djo.dir, SZDIRE); /* Save directory entry of the object */
memcpy(&djn, &djo, sizeof (DIR)); /* Duplicate the directory object */
res = follow_path(&djn, path_new); /* Make sure if new object name is not 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;
......@@ -5193,7 +5147,7 @@ FRESULT f_rename (
res = dir_register(&djn); /* Register the new entry */
if (res == FR_OK) {
dir = djn.dir; /* Copy directory entry of the object except name */
mem_cpy(dir + 13, buf + 13, SZDIRE - 13);
memcpy(dir + 13, buf + 13, SZDIRE - 13);
dir[DIR_Attr] = buf[DIR_Attr];
if (!(dir[DIR_Attr] & AM_DIR)) dir[DIR_Attr] |= AM_ARC; /* Set archive attribute if it is a file */
fs->wflag = 1;
......@@ -5359,15 +5313,16 @@ FRESULT f_getlabel (
#if FF_FS_EXFAT
if (fs->fs_type == FS_EXFAT) {
WCHAR hs;
UINT nw;
for (si = di = hs = 0; si < dj.dir[XDIR_NumLabel]; si++) { /* Extract volume label from 83 entry */
wc = ld_word(dj.dir + XDIR_Label + si * 2);
if (hs == 0 && IsSurrogate(wc)) { /* Is the code a surrogate? */
hs = wc; continue;
}
wc = put_utf((DWORD)hs << 16 | wc, &label[di], 4);
if (wc == 0) { di = 0; break; }
di += wc;
nw = put_utf((DWORD)hs << 16 | wc, &label[di], 4); /* Store it in API encoding */
if (nw == 0) { di = 0; break; } /* Encode error? */
di += nw;
hs = 0;
}
if (hs != 0) di = 0; /* Broken surrogate pair? */
......@@ -5380,10 +5335,9 @@ FRESULT f_getlabel (
wc = dj.dir[si++];
#if FF_USE_LFN && FF_LFN_UNICODE >= 1 /* Unicode output */
if (dbc_1st((BYTE)wc) && si < 11) wc = wc << 8 | dj.dir[si++]; /* Is it a DBC? */
wc = ff_oem2uni(wc, CODEPAGE); /* Convert it into Unicode */
if (wc != 0) wc = put_utf(wc, &label[di], 4); /* Put it in Unicode */
if (wc == 0) { di = 0; break; }
di += wc;
wc = ff_oem2uni(wc, CODEPAGE); /* Convert it into Unicode */
if (wc == 0) { di = 0; break; } /* Invalid char in current code page? */
di += put_utf(wc, &label[di], 4); /* Store it in Unicode */
#else /* ANSI/OEM output */
label[di++] = (TCHAR)wc;
#endif
......@@ -5407,10 +5361,12 @@ FRESULT f_getlabel (
if (res == FR_OK) {
switch (fs->fs_type) {
case FS_EXFAT:
di = BPB_VolIDEx; break;
di = BPB_VolIDEx;
break;
case FS_FAT32:
di = BS_VolID32; break;
di = BS_VolID32;
break;
default:
di = BS_VolID;
......@@ -5439,7 +5395,7 @@ FRESULT f_setlabel (
BYTE dirvn[22];
UINT di;
WCHAR wc;
static const char badchr[] = "+.,;=[]/\\\"*:<>\?|\x7F"; /* [0..] for FAT, [7..] for exFAT */
static const char badchr[18] = "+.,;=[]" "/*:<>|\\\"\?\x7F"; /* [0..16] for FAT, [7..16] for exFAT */
#if FF_USE_LFN
DWORD dc;
#endif
......@@ -5450,7 +5406,7 @@ FRESULT f_setlabel (
#if FF_FS_EXFAT
if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
mem_set(dirvn, 0, 22);
memset(dirvn, 0, 22);
di = 0;
while ((UINT)*label >= ' ') { /* Create volume label */
dc = tchar2uni(&label); /* Get a Unicode character */
......@@ -5461,7 +5417,7 @@ FRESULT f_setlabel (
st_word(dirvn + di * 2, (WCHAR)(dc >> 16)); di++;
}
}
if (dc == 0 || chk_chr(badchr + 7, (int)dc) || di >= 11) { /* Check validity of the volume label */
if (dc == 0 || strchr(&badchr[7], (int)dc) || di >= 11) { /* Check validity of the volume label */
LEAVE_FF(fs, FR_INVALID_NAME);
}
st_word(dirvn + di * 2, (WCHAR)dc); di++;
......@@ -5469,7 +5425,7 @@ FRESULT f_setlabel (
} else
#endif
{ /* On the FAT/FAT32 volume */
mem_set(dirvn, ' ', 11);
memset(dirvn, ' ', 11);
di = 0;
while ((UINT)*label >= ' ') { /* Create volume label */
#if FF_USE_LFN
......@@ -5485,7 +5441,7 @@ FRESULT f_setlabel (
if (wc >= 0x80) wc = ExCvt[wc - 0x80]; /* To upper extended characters (SBCS cfg) */
#endif
#endif
if (wc == 0 || chk_chr(badchr + 0, (int)wc) || di >= (UINT)((wc >= 0x100) ? 10 : 11)) { /* Reject invalid characters for volume label */
if (wc == 0 || strchr(&badchr[0], (int)wc) || di >= (UINT)((wc >= 0x100) ? 10 : 11)) { /* Reject invalid characters for volume label */
LEAVE_FF(fs, FR_INVALID_NAME);
}
if (wc >= 0x100) dirvn[di++] = (BYTE)(wc >> 8);
......@@ -5503,10 +5459,10 @@ FRESULT f_setlabel (
if (res == FR_OK) {
if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) {
dj.dir[XDIR_NumLabel] = (BYTE)di; /* Change the volume label */
mem_cpy(dj.dir + XDIR_Label, dirvn, 22);
memcpy(dj.dir + XDIR_Label, dirvn, 22);
} else {
if (di != 0) {
mem_cpy(dj.dir, dirvn, 11); /* Change the volume label */
memcpy(dj.dir, dirvn, 11); /* Change the volume label */
} else {
dj.dir[DIR_Name] = DDEM; /* Remove the volume label */
}
......@@ -5519,14 +5475,14 @@ FRESULT f_setlabel (
if (di != 0) { /* Create a volume label entry */
res = dir_alloc(&dj, 1); /* Allocate an entry */
if (res == FR_OK) {
mem_set(dj.dir, 0, SZDIRE); /* Clean the entry */
memset(dj.dir, 0, SZDIRE); /* Clean the entry */
if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) {
dj.dir[XDIR_Type] = ET_VLABEL; /* Create volume label entry */
dj.dir[XDIR_NumLabel] = (BYTE)di;
mem_cpy(dj.dir + XDIR_Label, dirvn, 22);
memcpy(dj.dir + XDIR_Label, dirvn, 22);
} else {
dj.dir[DIR_Attr] = AM_VOL; /* Create volume label entry */
mem_cpy(dj.dir, dirvn, 11);
memcpy(dj.dir, dirvn, 11);
}
fs->wflag = 1;
res = sync_fs(fs);
......@@ -5663,8 +5619,7 @@ FRESULT f_forward (
remain = fp->obj.objsize - fp->fptr;
if (btf > remain) btf = (UINT)remain; /* Truncate btf by remaining bytes */
for ( ; btf && (*func)(0, 0); /* Repeat until all data transferred or stream goes busy */
fp->fptr += rcnt, *bf += rcnt, btf -= rcnt) {
for ( ; btf > 0 && (*func)(0, 0); fp->fptr += rcnt, *bf += rcnt, btf -= rcnt) { /* Repeat until all data transferred or stream goes busy */
csect = (UINT)(fp->fptr / SS(fs) & (fs->csize - 1)); /* Sector offset in the cluster */
if (fp->fptr % SS(fs) == 0) { /* On the sector boundary? */
if (csect == 0) { /* On the cluster boundary? */
......@@ -5708,7 +5663,7 @@ FRESULT f_forward (
#if !FF_FS_READONLY && FF_USE_MKFS
/*-----------------------------------------------------------------------*/
/* Create an FAT/exFAT volume */
/* Create FAT/exFAT volume (with sub-functions) */
/*-----------------------------------------------------------------------*/
#define N_SEC_TRACK 63 /* Sectors per track for determination of drive CHS */
......@@ -5716,29 +5671,30 @@ FRESULT f_forward (
#define GPT_ITEMS 128 /* Number of GPT table size (>=128, sector aligned) */
/* Create partitions on the physical drive */
/* Create partitions on the physical drive in format of MBR or GPT */
static FRESULT create_partition (
BYTE drv, /* Physical drive number */
const LBA_t plst[], /* Partition list */
UINT sys, /* System ID (for only MBR, temp setting) and bit8:GPT */
BYTE sys, /* System ID (for only MBR, temp setting) */
BYTE* buf /* Working buffer for a sector */
)
{
UINT i, cy;
LBA_t sz_drv;
DWORD sz_drv32, s_lba32, n_lba32;
BYTE *pte, hd, n_hd, sc, n_sc;
DWORD sz_drv32, nxt_alloc32, sz_part32;
BYTE *pte;
BYTE hd, n_hd, sc, n_sc;
/* Get drive size */
/* Get physical drive size */
if (disk_ioctl(drv, GET_SECTOR_COUNT, &sz_drv) != RES_OK) return FR_DISK_ERR;
#if FF_LBA64
if (sz_drv >= FF_MIN_GPT) { /* Create partitions in GPT */
if (sz_drv >= FF_MIN_GPT) { /* Create partitions in GPT format */
WORD ss;
UINT sz_pt, pi, si, ofs;
UINT sz_ptbl, pi, si, ofs;
DWORD bcc, rnd, align;
QWORD s_lba64, n_lba64, sz_pool, s_bpt;
QWORD nxt_alloc, sz_part, sz_pool, top_bpt;
static const BYTE gpt_mbr[16] = {0x00, 0x00, 0x02, 0x00, 0xEE, 0xFE, 0xFF, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF};
#if FF_MAX_SS != FF_MIN_SS
......@@ -5747,103 +5703,103 @@ static FRESULT create_partition (
#else
ss = FF_MAX_SS;
#endif
rnd = GET_FATTIME(); /* Random seed */
align = GPT_ALIGN / ss; /* Partition alignment [sector] */
sz_pt = GPT_ITEMS * SZ_GPTE / ss; /* Size of PT [sector] */
s_bpt = sz_drv - sz_pt - 1; /* Backup PT start sector */
s_lba64 = 2 + sz_pt; /* First allocatable sector */
sz_pool = s_bpt - s_lba64; /* Size of allocatable area */
bcc = 0xFFFFFFFF; n_lba64 = 1;
rnd = (DWORD)sz_drv + GET_FATTIME(); /* Random seed */
align = GPT_ALIGN / ss; /* Partition alignment for GPT [sector] */
sz_ptbl = GPT_ITEMS * SZ_GPTE / ss; /* Size of partition table [sector] */
top_bpt = sz_drv - sz_ptbl - 1; /* Backup partiiton table start sector */
nxt_alloc = 2 + sz_ptbl; /* First allocatable sector */
sz_pool = top_bpt - nxt_alloc; /* Size of allocatable area */
bcc = 0xFFFFFFFF; sz_part = 1;
pi = si = 0; /* partition table index, size table index */
do {
if (pi * SZ_GPTE % ss == 0) mem_set(buf, 0, ss); /* Clean the buffer if needed */
if (n_lba64 != 0) { /* Is the size table not termintated? */
s_lba64 = (s_lba64 + align - 1) & ((QWORD)0 - align); /* Align partition start */
n_lba64 = plst[si++]; /* Get a partition size */
if (n_lba64 <= 100) { /* Is the size in percentage? */
n_lba64 = sz_pool * n_lba64 / 100;
n_lba64 = (n_lba64 + align - 1) & ((QWORD)0 - align); /* Align partition end (only if in percentage) */
if (pi * SZ_GPTE % ss == 0) memset(buf, 0, ss); /* Clean the buffer if needed */
if (sz_part != 0) { /* Is the size table not termintated? */
nxt_alloc = (nxt_alloc + align - 1) & ((QWORD)0 - align); /* Align partition start */
sz_part = plst[si++]; /* Get a partition size */
if (sz_part <= 100) { /* Is the size in percentage? */
sz_part = sz_pool * sz_part / 100;
sz_part = (sz_part + align - 1) & ((QWORD)0 - align); /* Align partition end (only if in percentage) */
}
if (s_lba64 + n_lba64 > s_bpt) { /* Clip at end of the pool */
n_lba64 = (s_lba64 < s_bpt) ? s_bpt - s_lba64 : 0;
if (nxt_alloc + sz_part > top_bpt) { /* Clip the size at end of the pool */
sz_part = (nxt_alloc < top_bpt) ? top_bpt - nxt_alloc : 0;
}
}
if (n_lba64 != 0) { /* Add a partition? */
if (sz_part != 0) { /* Add a partition? */
ofs = pi * SZ_GPTE % ss;
mem_cpy(buf + ofs + GPTE_PtGuid, GUID_MS_Basic, 16); /* Partition GUID (Microsoft Basic Data) */
rnd = make_rand(rnd, buf + ofs + GPTE_UpGuid, 16); /* Unique partition GUID */
st_qword(buf + ofs + GPTE_FstLba, s_lba64); /* Partition start LBA */
st_qword(buf + ofs + GPTE_LstLba, s_lba64 + n_lba64 - 1); /* Partition end LBA */
s_lba64 += n_lba64; /* Next partition LBA */
memcpy(buf + ofs + GPTE_PtGuid, GUID_MS_Basic, 16); /* Set partition GUID (Microsoft Basic Data) */
rnd = make_rand(rnd, buf + ofs + GPTE_UpGuid, 16); /* Set unique partition GUID */
st_qword(buf + ofs + GPTE_FstLba, nxt_alloc); /* Set partition start sector */
st_qword(buf + ofs + GPTE_LstLba, nxt_alloc + sz_part - 1); /* Set partition end sector */
nxt_alloc += sz_part; /* Next allocatable sector */
}
if ((pi + 1) * SZ_GPTE % ss == 0) { /* Write the buffer if it is filled up */
for (i = 0; i < ss; bcc = crc32(bcc, buf[i++])) ; /* Calculate table check sum */
if (disk_write(drv, buf, 2 + pi * SZ_GPTE / ss, 1) != RES_OK) return FR_DISK_ERR; /* Primary table */
if (disk_write(drv, buf, s_bpt + pi * SZ_GPTE / ss, 1) != RES_OK) return FR_DISK_ERR; /* Secondary table */
if (disk_write(drv, buf, 2 + pi * SZ_GPTE / ss, 1) != RES_OK) return FR_DISK_ERR; /* Write to primary table */
if (disk_write(drv, buf, top_bpt + pi * SZ_GPTE / ss, 1) != RES_OK) return FR_DISK_ERR; /* Write to secondary table */
}
} while (++pi < GPT_ITEMS);
/* Create primary GPT header */
mem_set(buf, 0, ss);
mem_cpy(buf + GPTH_Sign, "EFI PART" "\0\0\1\0" "\x5C\0\0", 16); /* Signature, version (1.0) and size (92) */
st_dword(buf + GPTH_PtBcc, ~bcc); /* Table check sum */
st_qword(buf + GPTH_CurLba, 1); /* LBA of this header */
st_qword(buf + GPTH_BakLba, sz_drv - 1); /* LBA of another header */
st_qword(buf + GPTH_FstLba, 2 + sz_pt); /* LBA of first allocatable sector */
st_qword(buf + GPTH_LstLba, s_bpt - 1); /* LBA of last allocatable sector */
st_dword(buf + GPTH_PteSize, SZ_GPTE); /* Size of a table entry */
st_dword(buf + GPTH_PtNum, GPT_ITEMS); /* Number of table entries */
st_dword(buf + GPTH_PtOfs, 2); /* LBA of this table */
memset(buf, 0, ss);
memcpy(buf + GPTH_Sign, "EFI PART" "\0\0\1\0" "\x5C\0\0", 16); /* Signature, version (1.0) and size (92) */
st_dword(buf + GPTH_PtBcc, ~bcc); /* Table check sum */
st_qword(buf + GPTH_CurLba, 1); /* LBA of this header */
st_qword(buf + GPTH_BakLba, sz_drv - 1); /* LBA of secondary header */
st_qword(buf + GPTH_FstLba, 2 + sz_ptbl); /* LBA of first allocatable sector */
st_qword(buf + GPTH_LstLba, top_bpt - 1); /* LBA of last allocatable sector */
st_dword(buf + GPTH_PteSize, SZ_GPTE); /* Size of a table entry */
st_dword(buf + GPTH_PtNum, GPT_ITEMS); /* Number of table entries */
st_dword(buf + GPTH_PtOfs, 2); /* LBA of this table */
rnd = make_rand(rnd, buf + GPTH_DskGuid, 16); /* Disk GUID */
for (i = 0, bcc= 0xFFFFFFFF; i < 92; bcc = crc32(bcc, buf[i++])) ; /* Calculate header check sum */
st_dword(buf + GPTH_Bcc, ~bcc); /* Header check sum */
st_dword(buf + GPTH_Bcc, ~bcc); /* Header check sum */
if (disk_write(drv, buf, 1, 1) != RES_OK) return FR_DISK_ERR;
/* Create secondary GPT header */
st_qword(buf + GPTH_CurLba, sz_drv - 1); /* LBA of this header */
st_qword(buf + GPTH_BakLba, 1); /* LBA of another header */
st_qword(buf + GPTH_PtOfs, s_bpt); /* LBA of this table */
st_qword(buf + GPTH_CurLba, sz_drv - 1); /* LBA of this header */
st_qword(buf + GPTH_BakLba, 1); /* LBA of primary header */
st_qword(buf + GPTH_PtOfs, top_bpt); /* LBA of this table */
st_dword(buf + GPTH_Bcc, 0);
for (i = 0, bcc= 0xFFFFFFFF; i < 92; bcc = crc32(bcc, buf[i++])) ; /* Calculate header check sum */
st_dword(buf + GPTH_Bcc, ~bcc); /* Header check sum */
st_dword(buf + GPTH_Bcc, ~bcc); /* Header check sum */
if (disk_write(drv, buf, sz_drv - 1, 1) != RES_OK) return FR_DISK_ERR;
/* Create protective MBR */
mem_set(buf, 0, ss);
mem_cpy(buf + MBR_Table, gpt_mbr, 16); /* Create a GPT partition */
memset(buf, 0, ss);
memcpy(buf + MBR_Table, gpt_mbr, 16); /* Create a GPT partition */
st_word(buf + BS_55AA, 0xAA55);
if (disk_write(drv, buf, 0, 1) != RES_OK) return FR_DISK_ERR;
} else
#endif
{ /* Create partitions in MBR */
{ /* Create partitions in MBR format */
sz_drv32 = (DWORD)sz_drv;
n_sc = N_SEC_TRACK; /* Determine drive CHS without any consideration of the drive geometry */
n_sc = N_SEC_TRACK; /* Determine drive CHS without any consideration of the drive geometry */
for (n_hd = 8; n_hd != 0 && sz_drv32 / n_hd / n_sc > 1024; n_hd *= 2) ;
if (n_hd == 0) n_hd = 255; /* Number of heads needs to be <256 */
if (n_hd == 0) n_hd = 255; /* Number of heads needs to be <256 */
mem_set(buf, 0, FF_MAX_SS); /* Clear MBR */
memset(buf, 0, FF_MAX_SS); /* Clear MBR */
pte = buf + MBR_Table; /* Partition table in the MBR */
for (i = 0, s_lba32 = n_sc; i < 4 && s_lba32 != 0 && s_lba32 < sz_drv32; i++, s_lba32 += n_lba32) {
n_lba32 = (DWORD)plst[i]; /* Get partition size */
if (n_lba32 <= 100) n_lba32 = (n_lba32 == 100) ? sz_drv32 : sz_drv32 / 100 * n_lba32; /* Size in percentage? */
if (s_lba32 + n_lba32 > sz_drv32 || s_lba32 + n_lba32 < s_lba32) n_lba32 = sz_drv32 - s_lba32; /* Clip at drive size */
if (n_lba32 == 0) break; /* End of table or no sector to allocate? */
st_dword(pte + PTE_StLba, s_lba32); /* Start LBA */
st_dword(pte + PTE_SizLba, n_lba32); /* Number of sectors */
pte[PTE_System] = (BYTE)sys; /* System type */
cy = (UINT)(s_lba32 / n_sc / n_hd); /* Start cylinder */
hd = (BYTE)(s_lba32 / n_sc % n_hd); /* Start head */
sc = (BYTE)(s_lba32 % n_sc + 1); /* Start sector */
for (i = 0, nxt_alloc32 = n_sc; i < 4 && nxt_alloc32 != 0 && nxt_alloc32 < sz_drv32; i++, nxt_alloc32 += sz_part32) {
sz_part32 = (DWORD)plst[i]; /* Get partition size */
if (sz_part32 <= 100) sz_part32 = (sz_part32 == 100) ? sz_drv32 : sz_drv32 / 100 * sz_part32; /* Size in percentage? */
if (nxt_alloc32 + sz_part32 > sz_drv32 || nxt_alloc32 + sz_part32 < nxt_alloc32) sz_part32 = sz_drv32 - nxt_alloc32; /* Clip at drive size */
if (sz_part32 == 0) break; /* End of table or no sector to allocate? */
st_dword(pte + PTE_StLba, nxt_alloc32); /* Start LBA */
st_dword(pte + PTE_SizLba, sz_part32); /* Number of sectors */
pte[PTE_System] = sys; /* System type */
cy = (UINT)(nxt_alloc32 / n_sc / n_hd); /* Start cylinder */
hd = (BYTE)(nxt_alloc32 / n_sc % n_hd); /* Start head */
sc = (BYTE)(nxt_alloc32 % n_sc + 1); /* Start sector */
pte[PTE_StHead] = hd;
pte[PTE_StSec] = (BYTE)((cy >> 2 & 0xC0) | sc);
pte[PTE_StCyl] = (BYTE)cy;
cy = (UINT)((s_lba32 + n_lba32 - 1) / n_sc / n_hd); /* End cylinder */
hd = (BYTE)((s_lba32 + n_lba32 - 1) / n_sc % n_hd); /* End head */
sc = (BYTE)((s_lba32 + n_lba32 - 1) % n_sc + 1); /* End sector */
cy = (UINT)((nxt_alloc32 + sz_part32 - 1) / n_sc / n_hd); /* End cylinder */
hd = (BYTE)((nxt_alloc32 + sz_part32 - 1) / n_sc % n_hd); /* End head */
sc = (BYTE)((nxt_alloc32 + sz_part32 - 1) % n_sc + 1); /* End sector */
pte[PTE_EdHead] = hd;
pte[PTE_EdSec] = (BYTE)((cy >> 2 & 0xC0) | sc);
pte[PTE_EdCyl] = (BYTE)cy;
......@@ -5872,7 +5828,7 @@ FRESULT f_mkfs (
static const MKFS_PARM defopt = {FM_ANY, 0, 0, 0, 0}; /* Default parameter */
BYTE fsopt, fsty, sys, *buf, *pte, pdrv, ipart;
WORD ss; /* Sector size */
DWORD sz_buf, sz_blk, n_clst, pau, nsect, n;
DWORD sz_buf, sz_blk, n_clst, pau, nsect, n, vsn;
LBA_t sz_vol, b_vol, b_fat, b_data; /* Size of volume, Base LBA of volume, fat, data */
LBA_t sect, lba[2];
DWORD sz_rsv, sz_fat, sz_dir, sz_au; /* Size of reserved, fat, dir, data, cluster */
......@@ -5938,7 +5894,7 @@ FRESULT f_mkfs (
ofs = i = 0;
while (n_ent) { /* Find MS Basic partition with order of ipart */
if (ofs == 0 && disk_read(pdrv, buf, pt_lba++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Get PT sector */
if (!mem_cmp(buf + ofs + GPTE_PtGuid, GUID_MS_Basic, 16) && ++i == ipart) { /* MS basic data partition? */
if (!memcmp(buf + ofs + GPTE_PtGuid, GUID_MS_Basic, 16) && ++i == ipart) { /* MS basic data partition? */
b_vol = ld_qword(buf + ofs + GPTE_FstLba);
sz_vol = ld_qword(buf + ofs + GPTE_LstLba) - b_vol + 1;
break;
......@@ -5974,7 +5930,7 @@ FRESULT f_mkfs (
}
if (sz_vol < 128) LEAVE_MKFS(FR_MKFS_ABORTED); /* Check if volume size is >=128s */
/* Now start to create a FAT volume at b_vol and sz_vol */
/* Now start to create an FAT volume at b_vol and sz_vol */
do { /* Pre-determine the FAT type */
if (FF_FS_EXFAT && (fsopt & FM_EXFAT)) { /* exFAT possible? */
......@@ -5995,12 +5951,13 @@ FRESULT f_mkfs (
fsty = FS_FAT16;
} while (0);
vsn = (DWORD)sz_vol + GET_FATTIME(); /* VSN generated from current time and partitiion size */
#if FF_FS_EXFAT
if (fsty == FS_EXFAT) { /* Create an exFAT volume */
DWORD szb_bit, szb_case, sum, nb, cl, tbl[3];
DWORD szb_bit, szb_case, sum, nbit, clu, clen[3];
WCHAR ch, si;
UINT j, st;
BYTE b;
if (sz_vol < 0x1000) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume for exFAT? */
#if FF_USE_TRIM
......@@ -6021,12 +5978,12 @@ FRESULT f_mkfs (
if (n_clst <16) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too few clusters? */
if (n_clst > MAX_EXFAT) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too many clusters? */
szb_bit = (n_clst + 7) / 8; /* Size of allocation bitmap */
tbl[0] = (szb_bit + sz_au * ss - 1) / (sz_au * ss); /* Number of allocation bitmap clusters */
szb_bit = (n_clst + 7) / 8; /* Size of allocation bitmap */
clen[0] = (szb_bit + sz_au * ss - 1) / (sz_au * ss); /* Number of allocation bitmap clusters */
/* Create a compressed up-case table */
sect = b_data + sz_au * tbl[0]; /* Table start sector */
sum = 0; /* Table checksum to be stored in the 82 entry */
sect = b_data + sz_au * clen[0]; /* Table start sector */
sum = 0; /* Table checksum to be stored in the 82 entry */
st = 0; si = 0; i = 0; j = 0; szb_case = 0;
do {
switch (st) {
......@@ -6037,10 +5994,10 @@ FRESULT f_mkfs (
}
for (j = 1; (WCHAR)(si + j) && (WCHAR)(si + j) == ff_wtoupper((WCHAR)(si + j)); j++) ; /* Get run length of no-case block */
if (j >= 128) {
ch = 0xFFFF; st = 2; break; /* Compress the no-case block if run is >= 128 */
ch = 0xFFFF; st = 2; break; /* Compress the no-case block if run is >= 128 chars */
}
st = 1; /* Do not compress short run */
/* go to next case */
/* FALLTHROUGH */
case 1:
ch = si++; /* Fill the short run */
if (--j == 0) st = 0;
......@@ -6050,7 +6007,7 @@ FRESULT f_mkfs (
ch = (WCHAR)j; si += (WCHAR)j; /* Number of chars to skip */
st = 0;
}
sum = xsum32(buf[i + 0] = (BYTE)ch, sum); /* Put it into the write buffer */
sum = xsum32(buf[i + 0] = (BYTE)ch, sum); /* Put it into the write buffer */
sum = xsum32(buf[i + 1] = (BYTE)(ch >> 8), sum);
i += 2; szb_case += 2;
if (si == 0 || i == sz_buf * ss) { /* Write buffered data when buffer full or end of process */
......@@ -6059,16 +6016,15 @@ FRESULT f_mkfs (
sect += n; i = 0;
}
} while (si);
tbl[1] = (szb_case + sz_au * ss - 1) / (sz_au * ss); /* Number of up-case table clusters */
tbl[2] = 1; /* Number of root dir clusters */
clen[1] = (szb_case + sz_au * ss - 1) / (sz_au * ss); /* Number of up-case table clusters */
clen[2] = 1; /* Number of root dir clusters */
/* Initialize the allocation bitmap */
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 */
sect = b_data; nsect = (szb_bit + ss - 1) / ss; /* Start of bitmap and number of bitmap sectors */
nbit = clen[0] + clen[1] + clen[2]; /* Number of clusters in-use by system (bitmap, up-case and root-dir) */
do {
mem_set(buf, 0, sz_buf * ss);
for (i = 0; nb >= 8 && i < sz_buf * ss; buf[i++] = 0xFF, nb -= 8) ;
for (b = 1; nb != 0 && i < sz_buf * ss; buf[i] |= b, b <<= 1, nb--) ;
memset(buf, 0, sz_buf * ss); /* Initialize bitmap buffer */
for (i = 0; nbit != 0 && i / 8 < sz_buf * ss; buf[i / 8] |= 1 << (i % 8), i++, nbit--) ; /* Mark used clusters */
n = (nsect > sz_buf) ? sz_buf : nsect; /* Write the buffered data */
if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
sect += n; nsect -= n;
......@@ -6076,40 +6032,40 @@ FRESULT f_mkfs (
/* Initialize the FAT */
sect = b_fat; nsect = sz_fat; /* Start of FAT and number of FAT sectors */
j = nb = cl = 0;
j = nbit = clu = 0;
do {
mem_set(buf, 0, sz_buf * ss); i = 0; /* Clear work area and reset write index */
if (cl == 0) { /* Set FAT [0] and FAT[1] */
st_dword(buf + i, 0xFFFFFFF8); i += 4; cl++;
st_dword(buf + i, 0xFFFFFFFF); i += 4; cl++;
memset(buf, 0, sz_buf * ss); i = 0; /* Clear work area and reset write offset */
if (clu == 0) { /* Initialize FAT [0] and FAT[1] */
st_dword(buf + i, 0xFFFFFFF8); i += 4; clu++;
st_dword(buf + i, 0xFFFFFFFF); i += 4; clu++;
}
do { /* Create chains of bitmap, up-case and root dir */
while (nb != 0 && i < sz_buf * ss) { /* Create a chain */
st_dword(buf + i, (nb > 1) ? cl + 1 : 0xFFFFFFFF);
i += 4; cl++; nb--;
while (nbit != 0 && i < sz_buf * ss) { /* Create a chain */
st_dword(buf + i, (nbit > 1) ? clu + 1 : 0xFFFFFFFF);
i += 4; clu++; nbit--;
}
if (nb == 0 && j < 3) nb = tbl[j++]; /* Next chain */
} while (nb != 0 && i < sz_buf * ss);
if (nbit == 0 && j < 3) nbit = clen[j++]; /* Get next chain length */
} while (nbit != 0 && i < sz_buf * ss);
n = (nsect > sz_buf) ? sz_buf : nsect; /* Write the buffered data */
if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
sect += n; nsect -= n;
} while (nsect);
/* Initialize the root directory */
mem_set(buf, 0, sz_buf * ss);
buf[SZDIRE * 0 + 0] = ET_VLABEL; /* Volume label entry (no label) */
buf[SZDIRE * 1 + 0] = ET_BITMAP; /* Bitmap entry */
st_dword(buf + SZDIRE * 1 + 20, 2); /* cluster */
st_dword(buf + SZDIRE * 1 + 24, szb_bit); /* size */
buf[SZDIRE * 2 + 0] = ET_UPCASE; /* Up-case table entry */
st_dword(buf + SZDIRE * 2 + 4, sum); /* sum */
st_dword(buf + SZDIRE * 2 + 20, 2 + tbl[0]); /* cluster */
st_dword(buf + SZDIRE * 2 + 24, szb_case); /* size */
sect = b_data + sz_au * (tbl[0] + tbl[1]); nsect = sz_au; /* Start of the root directory and number of sectors */
memset(buf, 0, sz_buf * ss);
buf[SZDIRE * 0 + 0] = ET_VLABEL; /* Volume label entry (no label) */
buf[SZDIRE * 1 + 0] = ET_BITMAP; /* Bitmap entry */
st_dword(buf + SZDIRE * 1 + 20, 2); /* cluster */
st_dword(buf + SZDIRE * 1 + 24, szb_bit); /* size */
buf[SZDIRE * 2 + 0] = ET_UPCASE; /* Up-case table entry */
st_dword(buf + SZDIRE * 2 + 4, sum); /* sum */
st_dword(buf + SZDIRE * 2 + 20, 2 + clen[0]); /* cluster */
st_dword(buf + SZDIRE * 2 + 24, szb_case); /* size */
sect = b_data + sz_au * (clen[0] + clen[1]); nsect = sz_au; /* Start of the root directory and number of sectors */
do { /* Fill root directory sectors */
n = (nsect > sz_buf) ? sz_buf : nsect;
if (disk_write(pdrv, buf, sect, n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
mem_set(buf, 0, ss);
memset(buf, 0, ss); /* Rest of entries are filled with zero */
sect += n; nsect -= n;
} while (nsect);
......@@ -6117,16 +6073,16 @@ FRESULT f_mkfs (
sect = b_vol;
for (n = 0; n < 2; n++) {
/* Main record (+0) */
mem_set(buf, 0, ss);
mem_cpy(buf + BS_JmpBoot, "\xEB\x76\x90" "EXFAT ", 11); /* Boot jump code (x86), OEM name */
memset(buf, 0, ss);
memcpy(buf + BS_JmpBoot, "\xEB\x76\x90" "EXFAT ", 11); /* Boot jump code (x86), OEM name */
st_qword(buf + BPB_VolOfsEx, b_vol); /* Volume offset in the physical drive [sector] */
st_qword(buf + BPB_TotSecEx, sz_vol); /* Volume size [sector] */
st_dword(buf + BPB_FatOfsEx, (DWORD)(b_fat - b_vol)); /* FAT offset [sector] */
st_dword(buf + BPB_FatSzEx, sz_fat); /* FAT size [sector] */
st_dword(buf + BPB_DataOfsEx, (DWORD)(b_data - b_vol)); /* Data offset [sector] */
st_dword(buf + BPB_NumClusEx, n_clst); /* Number of clusters */
st_dword(buf + BPB_RootClusEx, 2 + tbl[0] + tbl[1]); /* Root dir cluster # */
st_dword(buf + BPB_VolIDEx, GET_FATTIME()); /* VSN */
st_dword(buf + BPB_RootClusEx, 2 + clen[0] + clen[1]); /* Root dir cluster # */
st_dword(buf + BPB_VolIDEx, vsn); /* VSN */
st_word(buf + BPB_FSVerEx, 0x100); /* Filesystem version (1.00) */
for (buf[BPB_BytsPerSecEx] = 0, i = ss; i >>= 1; buf[BPB_BytsPerSecEx]++) ; /* Log2 of sector size [byte] */
for (buf[BPB_SecPerClusEx] = 0, i = sz_au; i >>= 1; buf[BPB_SecPerClusEx]++) ; /* Log2 of cluster size [sector] */
......@@ -6139,14 +6095,14 @@ FRESULT f_mkfs (
}
if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
/* Extended bootstrap record (+1..+8) */
mem_set(buf, 0, ss);
memset(buf, 0, ss);
st_word(buf + ss - 2, 0xAA55); /* Signature (placed at end of sector) */
for (j = 1; j < 9; j++) {
for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ; /* VBR checksum */
if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
}
/* OEM/Reserved record (+9..+10) */
mem_set(buf, 0, ss);
memset(buf, 0, ss);
for ( ; j < 11; j++) {
for (i = 0; i < ss; sum = xsum32(buf[i++], sum)) ; /* VBR checksum */
if (disk_write(pdrv, buf, sect++, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
......@@ -6214,7 +6170,7 @@ FRESULT f_mkfs (
if (fsty == FS_FAT16) {
if (n_clst > MAX_FAT16) { /* Too many clusters for FAT16 */
if (sz_au == 0 && (pau * 2) <= 64) {
sz_au = pau * 2; continue; /* Adjust cluster size and retry */
sz_au = pau * 2; continue; /* Adjust cluster size and retry */
}
if ((fsopt & FM_FAT32)) {
fsty = FS_FAT32; continue; /* Switch type to FAT32 and retry */
......@@ -6238,8 +6194,8 @@ FRESULT f_mkfs (
disk_ioctl(pdrv, CTRL_TRIM, lba);
#endif
/* Create FAT VBR */
mem_set(buf, 0, ss);
mem_cpy(buf + BS_JmpBoot, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code (x86), OEM name */
memset(buf, 0, ss);
memcpy(buf + BS_JmpBoot, "\xEB\xFE\x90" "MSDOS5.0", 11); /* Boot jump code (x86), OEM name */
st_word(buf + BPB_BytsPerSec, ss); /* Sector size [byte] */
buf[BPB_SecPerClus] = (BYTE)pau; /* Cluster size [sector] */
st_word(buf + BPB_RsvdSecCnt, (WORD)sz_rsv); /* Size of reserved area */
......@@ -6255,20 +6211,20 @@ FRESULT f_mkfs (
st_word(buf + BPB_NumHeads, 255); /* Number of heads (for int13) */
st_dword(buf + BPB_HiddSec, (DWORD)b_vol); /* Volume offset in the physical drive [sector] */
if (fsty == FS_FAT32) {
st_dword(buf + BS_VolID32, GET_FATTIME()); /* VSN */
st_dword(buf + BS_VolID32, vsn); /* VSN */
st_dword(buf + BPB_FATSz32, sz_fat); /* FAT size [sector] */
st_dword(buf + BPB_RootClus32, 2); /* Root directory cluster # (2) */
st_word(buf + BPB_FSInfo32, 1); /* Offset of FSINFO sector (VBR + 1) */
st_word(buf + BPB_BkBootSec32, 6); /* Offset of backup VBR (VBR + 6) */
buf[BS_DrvNum32] = 0x80; /* Drive number (for int13) */
buf[BS_BootSig32] = 0x29; /* Extended boot signature */
mem_cpy(buf + BS_VolLab32, "NO NAME " "FAT32 ", 19); /* Volume label, FAT signature */
memcpy(buf + BS_VolLab32, "NO NAME " "FAT32 ", 19); /* Volume label, FAT signature */
} else {
st_dword(buf + BS_VolID, GET_FATTIME()); /* VSN */
st_dword(buf + BS_VolID, vsn); /* VSN */
st_word(buf + BPB_FATSz16, (WORD)sz_fat); /* FAT size [sector] */
buf[BS_DrvNum] = 0x80; /* Drive number (for int13) */
buf[BS_BootSig] = 0x29; /* Extended boot signature */
mem_cpy(buf + BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */
memcpy(buf + BS_VolLab, "NO NAME " "FAT ", 19); /* Volume label, FAT signature */
}
st_word(buf + BS_55AA, 0xAA55); /* Signature (offset is fixed here regardless of sector size) */
if (disk_write(pdrv, buf, b_vol, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it to the VBR sector */
......@@ -6276,7 +6232,7 @@ FRESULT f_mkfs (
/* Create FSINFO record if needed */
if (fsty == FS_FAT32) {
disk_write(pdrv, buf, b_vol + 6, 1); /* Write backup VBR (VBR + 6) */
mem_set(buf, 0, ss);
memset(buf, 0, ss);
st_dword(buf + FSI_LeadSig, 0x41615252);
st_dword(buf + FSI_StrucSig, 0x61417272);
st_dword(buf + FSI_Free_Count, n_clst - 1); /* Number of free clusters */
......@@ -6287,7 +6243,7 @@ FRESULT f_mkfs (
}
/* Initialize FAT area */
mem_set(buf, 0, sz_buf * ss);
memset(buf, 0, sz_buf * ss);
sect = b_fat; /* FAT start sector */
for (i = 0; i < n_fat; i++) { /* Initialize FATs each */
if (fsty == FS_FAT32) {
......@@ -6301,7 +6257,7 @@ FRESULT f_mkfs (
do { /* Fill FAT sectors */
n = (nsect > sz_buf) ? sz_buf : nsect;
if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR);
mem_set(buf, 0, ss); /* Rest of FAT all are cleared */
memset(buf, 0, ss); /* Rest of FAT all are cleared */
sect += n; nsect -= n;
} while (nsect);
}
......@@ -6341,8 +6297,8 @@ FRESULT f_mkfs (
if (disk_write(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Write it back to the MBR */
}
} else { /* Volume as a new single partition */
if (!(fsopt & FM_SFD)) { /* Create partition table if not in SFD */
lba[0] = sz_vol, lba[1] = 0;
if (!(fsopt & FM_SFD)) { /* Create partition table if not in SFD */
lba[0] = sz_vol; lba[1] = 0;
fr = create_partition(pdrv, lba, sys, buf);
if (fr != FR_OK) LEAVE_MKFS(fr);
}
......@@ -6425,12 +6381,12 @@ TCHAR* f_gets (
if (rc != 1) break; /* EOF? */
wc = s[0];
if (dbc_1st((BYTE)wc)) { /* DBC 1st byte? */
f_read(fp, s, 1, &rc); /* Get DBC 2nd byte */
f_read(fp, s, 1, &rc); /* Get 2nd byte */
if (rc != 1 || !dbc_2nd(s[0])) continue; /* Wrong code? */
wc = wc << 8 | s[0];
}
dc = ff_oem2uni(wc, CODEPAGE); /* OEM --> */
if (dc == 0) continue;
dc = ff_oem2uni(wc, CODEPAGE); /* Convert ANSI/OEM into Unicode */
if (dc == 0) continue; /* Conversion error? */
#elif FF_STRF_ENCODE == 1 || FF_STRF_ENCODE == 2 /* Read a character in UTF-16LE/BE */
f_read(fp, s, 2, &rc); /* Get a code unit */
if (rc != 2) break; /* EOF? */
......@@ -6453,7 +6409,7 @@ TCHAR* f_gets (
if ((dc & 0xF0) == 0xE0) { dc &= 0x0F; ct = 2; } /* 3-byte sequence? */
if ((dc & 0xF8) == 0xF0) { dc &= 0x07; ct = 3; } /* 4-byte sequence? */
if (ct == 0) continue;
f_read(fp, s, ct, &rc); /* Get trailing bytes */
f_read(fp, s, ct, &rc); /* Get trailing bytes */
if (rc != ct) break;
rc = 0;
do { /* Merge the byte sequence */
......@@ -6522,11 +6478,14 @@ TCHAR* f_gets (
#if !FF_FS_READONLY
#include <stdarg.h>
#define SZ_PUTC_BUF 64
#define SZ_NUM_BUF 32
/*-----------------------------------------------------------------------*/
/* Put a Character to the File (sub-functions) */
/* Put a Character to the File (with sub-functions) */
/*-----------------------------------------------------------------------*/
/* Putchar output buffer and work area */
/* Output buffer and work area */
typedef struct {
FIL *fp; /* Ptr to the writing file */
......@@ -6537,11 +6496,11 @@ typedef struct {
BYTE bs[4];
UINT wi, ct;
#endif
BYTE buf[64]; /* Write buffer */
BYTE buf[SZ_PUTC_BUF]; /* Write buffer */
} putbuff;
/* Buffered write with code conversion */
/* Buffered file write with code conversion */
static void putc_bfd (putbuff* pb, TCHAR c)
{
......@@ -6551,7 +6510,7 @@ static void putc_bfd (putbuff* pb, TCHAR c)
WCHAR hs, wc;
#if FF_LFN_UNICODE == 2
DWORD dc;
TCHAR *tp;
const TCHAR *tp;
#endif
#endif
......@@ -6560,7 +6519,7 @@ static void putc_bfd (putbuff* pb, TCHAR c)
}
i = pb->idx; /* Write index of pb->buf[] */
if (i < 0) return;
if (i < 0) return; /* In write error? */
nc = pb->nchr; /* Write unit counter */
#if FF_USE_LFN && FF_LFN_UNICODE
......@@ -6593,7 +6552,7 @@ static void putc_bfd (putbuff* pb, TCHAR c)
return;
}
}
tp = (TCHAR*)pb->bs;
tp = (const TCHAR*)pb->bs;
dc = tchar2uni(&tp); /* UTF-8 ==> UTF-16 */
if (dc == 0xFFFFFFFF) return; /* Wrong code? */
wc = (WCHAR)dc;
......@@ -6659,7 +6618,7 @@ static void putc_bfd (putbuff* pb, TCHAR c)
pb->buf[i++] = (BYTE)wc;
#endif
#else /* ANSI/OEM input (without re-encoding) */
#else /* ANSI/OEM input (without re-encoding) */
pb->buf[i++] = (BYTE)c;
#endif
......@@ -6681,7 +6640,7 @@ static int putc_flush (putbuff* pb)
if ( pb->idx >= 0 /* Flush buffered characters to the file */
&& f_write(pb->fp, pb->buf, (UINT)pb->idx, &nw) == FR_OK
&& (UINT)pb->idx == nw) return pb->nchr;
return EOF;
return -1;
}
......@@ -6689,7 +6648,7 @@ static int putc_flush (putbuff* pb)
static void putc_init (putbuff* pb, FIL* fp)
{
mem_set(pb, 0, sizeof (putbuff));
memset(pb, 0, sizeof (putbuff));
pb->fp = fp;
}
......@@ -6732,8 +6691,129 @@ int f_puts (
/*-----------------------------------------------------------------------*/
/* Put a Formatted String to the File */
/* Put a Formatted String to the File (with sub-functions) */
/*-----------------------------------------------------------------------*/
#if FF_PRINT_FLOAT && FF_INTDEF == 2
#include <math.h>
static int ilog10 (double n) /* Calculate log10(n) in integer output */
{
int rv = 0;
while (n >= 10) { /* Decimate digit in right shift */
if (n >= 100000) {
n /= 100000; rv += 5;
} else {
n /= 10; rv++;
}
}
while (n < 1) { /* Decimate digit in left shift */
if (n < 0.00001) {
n *= 100000; rv -= 5;
} else {
n *= 10; rv--;
}
}
return rv;
}
static double i10x (int n) /* Calculate 10^n in integer input */
{
double rv = 1;
while (n > 0) { /* Left shift */
if (n >= 5) {
rv *= 100000; n -= 5;
} else {
rv *= 10; n--;
}
}
while (n < 0) { /* Right shift */
if (n <= -5) {
rv /= 100000; n += 5;
} else {
rv /= 10; n++;
}
}
return rv;
}
static void ftoa (
char* buf, /* Buffer to output the floating point string */
double val, /* Value to output */
int prec, /* Number of fractional digits */
TCHAR fmt /* Notation */
)
{
int d;
int e = 0, m = 0;
char sign = 0;
double w;
const char *er = 0;
const char ds = FF_PRINT_FLOAT == 2 ? ',' : '.';
if (isnan(val)) { /* Not a number? */
er = "NaN";
} else {
if (prec < 0) prec = 6; /* Default precision? (6 fractional digits) */
if (val < 0) { /* Nagative? */
val = 0 - val; sign = '-';
} else {
sign = '+';
}
if (isinf(val)) { /* Infinite? */
er = "INF";
} else {
if (fmt == 'f') { /* Decimal notation? */
val += i10x(0 - prec) / 2; /* Round (nearest) */
m = ilog10(val);
if (m < 0) m = 0;
if (m + prec + 3 >= SZ_NUM_BUF) er = "OV"; /* Buffer overflow? */
} else { /* E notation */
if (val != 0) { /* Not a true zero? */
val += i10x(ilog10(val) - prec) / 2; /* Round (nearest) */
e = ilog10(val);
if (e > 99 || prec + 7 >= SZ_NUM_BUF) { /* Buffer overflow or E > +99? */
er = "OV";
} else {
if (e < -99) e = -99;
val /= i10x(e); /* Normalize */
}
}
}
}
if (!er) { /* Not error condition */
if (sign == '-') *buf++ = sign; /* Add a - if negative value */
do { /* Put decimal number */
if (m == -1) *buf++ = ds; /* Insert a decimal separator when get into fractional part */
w = i10x(m); /* Snip the highest digit d */
d = (int)(val / w); val -= d * w;
*buf++ = (char)('0' + d); /* Put the digit */
} while (--m >= -prec); /* Output all digits specified by prec */
if (fmt != 'f') { /* Put exponent if needed */
*buf++ = (char)fmt;
if (e < 0) {
e = 0 - e; *buf++ = '-';
} else {
*buf++ = '+';
}
*buf++ = (char)('0' + e / 10);
*buf++ = (char)('0' + e % 10);
}
}
}
if (er) { /* Error condition */
if (sign) *buf++ = sign; /* Add sign if needed */
do *buf++ = *er++; while (*er); /* Put error symbol */
}
*buf = 0; /* Term */
}
#endif /* FF_PRINT_FLOAT && FF_INTDEF == 2 */
int f_printf (
FIL* fp, /* Pointer to the file object */
......@@ -6743,10 +6823,16 @@ int f_printf (
{
va_list arp;
putbuff pb;
BYTE f, r;
UINT i, j, w;
UINT i, j, w, f, r;
int prec;
#if FF_PRINT_LLI && FF_INTDEF == 2
QWORD v;
#else
DWORD v;
TCHAR c, d, str[32], *p;
#endif
TCHAR tc, pad, *tp;
TCHAR nul = 0;
char d, str[SZ_NUM_BUF];
putc_init(&pb, fp);
......@@ -6754,88 +6840,122 @@ int f_printf (
va_start(arp, fmt);
for (;;) {
c = *fmt++;
if (c == 0) break; /* End of string */
if (c != '%') { /* Non escape character */
putc_bfd(&pb, c);
tc = *fmt++;
if (tc == 0) break; /* End of format string */
if (tc != '%') { /* Not an escape character (pass-through) */
putc_bfd(&pb, tc);
continue;
}
w = f = 0;
c = *fmt++;
if (c == '0') { /* Flag: '0' padding */
f = 1; c = *fmt++;
} else {
if (c == '-') { /* Flag: left justified */
f = 2; c = *fmt++;
}
f = w = 0; pad = ' '; prec = -1; /* Initialize parms */
tc = *fmt++;
if (tc == '0') { /* Flag: '0' padded */
pad = '0'; tc = *fmt++;
} else if (tc == '-') { /* Flag: Left aligned */
f = 2; tc = *fmt++;
}
if (c == '*') { /* Minimum width by argument */
if (tc == '*') { /* Minimum width from an argument */
w = va_arg(arp, int);
c = *fmt++;
tc = *fmt++;
} else {
while (IsDigit(c)) { /* Minimum width */
w = w * 10 + c - '0';
c = *fmt++;
}
}
if (c == 'l' || c == 'L') { /* Type prefix: Size is long int */
f |= 4; c = *fmt++;
}
if (c == 0) break;
d = c;
if (IsLower(d)) d -= 0x20;
switch (d) { /* Atgument type is... */
case 'S' : /* String */
p = va_arg(arp, TCHAR*);
for (j = 0; p[j]; j++) ;
if (!(f & 2)) { /* Right padded */
while (j++ < w) putc_bfd(&pb, ' ') ;
}
while (*p) putc_bfd(&pb, *p++) ; /* String body */
while (j++ < w) putc_bfd(&pb, ' ') ; /* Left padded */
continue;
case 'C' : /* Character */
putc_bfd(&pb, (TCHAR)va_arg(arp, int)); continue;
case 'B' : /* Unsigned binary */
while (IsDigit(tc)) { /* Minimum width */
w = w * 10 + tc - '0';
tc = *fmt++;
}
}
if (tc == '.') { /* Precision */
tc = *fmt++;
if (tc == '*') { /* Precision from an argument */
prec = va_arg(arp, int);
tc = *fmt++;
} else {
prec = 0;
while (IsDigit(tc)) { /* Precision */
prec = prec * 10 + tc - '0';
tc = *fmt++;
}
}
}
if (tc == 'l') { /* Size: long int */
f |= 4; tc = *fmt++;
#if FF_PRINT_LLI && FF_INTDEF == 2
if (tc == 'l') { /* Size: long long int */
f |= 8; tc = *fmt++;
}
#endif
}
if (tc == 0) break; /* End of format string */
switch (tc) { /* Atgument type is... */
case 'b': /* Unsigned binary */
r = 2; break;
case 'O' : /* Unsigned octal */
case 'o': /* Unsigned octal */
r = 8; break;
case 'D' : /* Signed decimal */
case 'U' : /* Unsigned decimal */
case 'd': /* Signed decimal */
case 'u': /* Unsigned decimal */
r = 10; break;
case 'X' : /* Unsigned hexdecimal */
case 'x': /* Unsigned hexdecimal (lower case) */
case 'X': /* Unsigned hexdecimal (upper case) */
r = 16; break;
case 'c': /* Character */
putc_bfd(&pb, (TCHAR)va_arg(arp, int));
continue;
case 's': /* String */
tp = va_arg(arp, TCHAR*); /* Get a pointer argument */
if (!tp) tp = &nul; /* Null ptr generates a null string */
for (j = 0; tp[j]; j++) ; /* j = tcslen(tp) */
if (prec >= 0 && j > (UINT)prec) j = prec; /* Limited length of string body */
for ( ; !(f & 2) && j < w; j++) putc_bfd(&pb, pad); /* Left pads */
while (*tp && prec--) putc_bfd(&pb, *tp++); /* Body */
while (j++ < w) putc_bfd(&pb, ' '); /* Right pads */
continue;
#if FF_PRINT_FLOAT && FF_INTDEF == 2
case 'f': /* Floating point (decimal) */
case 'e': /* Floating point (e) */
case 'E': /* Floating point (E) */
ftoa(str, va_arg(arp, double), prec, tc); /* Make a flaoting point string */
for (j = strlen(str); !(f & 2) && j < w; j++) putc_bfd(&pb, pad); /* Left pads */
for (i = 0; str[i]; putc_bfd(&pb, str[i++])) ; /* Body */
while (j++ < w) putc_bfd(&pb, ' '); /* Right pads */
continue;
#endif
default: /* Unknown type (pass-through) */
putc_bfd(&pb, c); continue;
putc_bfd(&pb, tc); continue;
}
/* Get an argument and put it in numeral */
v = (f & 4) ? (DWORD)va_arg(arp, long) : ((d == 'D') ? (DWORD)(long)va_arg(arp, int) : (DWORD)va_arg(arp, unsigned int));
if (d == 'D' && (v & 0x80000000)) {
v = 0 - v;
f |= 8;
/* Get an integer argument and put it in numeral */
#if FF_PRINT_LLI && FF_INTDEF == 2
if (f & 8) { /* long long argument? */
v = (QWORD)va_arg(arp, LONGLONG);
} else {
if (f & 4) { /* long argument? */
v = (tc == 'd') ? (QWORD)(LONGLONG)va_arg(arp, long) : (QWORD)va_arg(arp, unsigned long);
} else { /* int/short/char argument */
v = (tc == 'd') ? (QWORD)(LONGLONG)va_arg(arp, int) : (QWORD)va_arg(arp, unsigned int);
}
}
if (tc == 'd' && (v & 0x8000000000000000)) { /* Negative value? */
v = 0 - v; f |= 1;
}
#else
if (f & 4) { /* long argument? */
v = (DWORD)va_arg(arp, long);
} else { /* int/short/char argument */
v = (tc == 'd') ? (DWORD)(long)va_arg(arp, int) : (DWORD)va_arg(arp, unsigned int);
}
if (tc == 'd' && (v & 0x80000000)) { /* Negative value? */
v = 0 - v; f |= 1;
}
#endif
i = 0;
do {
d = (TCHAR)(v % r); v /= r;
if (d > 9) d += (c == 'x') ? 0x27 : 0x07;
do { /* Make an integer number string */
d = (char)(v % r); v /= r;
if (d > 9) d += (tc == 'x') ? 0x27 : 0x07;
str[i++] = d + '0';
} while (v && i < sizeof str / sizeof *str);
if (f & 8) str[i++] = '-';
j = i; d = (f & 1) ? '0' : ' ';
if (!(f & 2)) {
while (j++ < w) putc_bfd(&pb, d); /* Right pad */
}
do {
putc_bfd(&pb, str[--i]); /* Number body */
} while (i);
while (j++ < w) putc_bfd(&pb, d); /* Left pad */
} while (v && i < SZ_NUM_BUF);
if (f & 1) str[i++] = '-'; /* Sign */
/* Write it */
for (j = i; !(f & 2) && j < w; j++) putc_bfd(&pb, pad); /* Left pads */
do putc_bfd(&pb, (TCHAR)str[--i]); while (i); /* Body */
while (j++ < w) putc_bfd(&pb, ' '); /* Right pads */
}
va_end(arp);
......@@ -6857,8 +6977,8 @@ FRESULT f_setcp (
WORD cp /* Value to be set as active code page */
)
{
static const WORD validcp[] = { 437, 720, 737, 771, 775, 850, 852, 857, 860, 861, 862, 863, 864, 865, 866, 869, 932, 936, 949, 950, 0};
static const BYTE* const tables[] = {Ct437, Ct720, Ct737, Ct771, Ct775, Ct850, Ct852, Ct857, Ct860, Ct861, Ct862, Ct863, Ct864, Ct865, Ct866, Ct869, Dc932, Dc936, Dc949, Dc950, 0};
static const WORD validcp[22] = { 437, 720, 737, 771, 775, 850, 852, 855, 857, 860, 861, 862, 863, 864, 865, 866, 869, 932, 936, 949, 950, 0};
static const BYTE* const tables[22] = {Ct437, Ct720, Ct737, Ct771, Ct775, Ct850, Ct852, Ct855, Ct857, Ct860, Ct861, Ct862, Ct863, Ct864, Ct865, Ct866, Ct869, Dc932, Dc936, Dc949, Dc950, 0};
UINT i;
......@@ -6877,18 +6997,3 @@ FRESULT f_setcp (
}
#endif /* FF_CODE_PAGE == 0 */
#include <rtthread.h>
#if FF_VOLUMES > 1
int elm_get_vol(FATFS *fat)
{
int vol;
for (vol = 0; vol < FF_VOLUMES; vol ++)
{
if (FatFs[vol] == fat) return vol;
}
return -1;
}
#endif
/*----------------------------------------------------------------------------/
/ FatFs - Generic FAT Filesystem module R0.14 /
/ FatFs - Generic FAT Filesystem module R0.14b /
/-----------------------------------------------------------------------------/
/
/ Copyright (C) 2019, ChaN, all right reserved.
/ Copyright (C) 2021, ChaN, all right reserved.
/
/ FatFs module is an open source software. Redistribution and use of FatFs in
/ source and binary forms, with or without modification, are permitted provided
......@@ -20,13 +20,12 @@
#ifndef FF_DEFINED
#define FF_DEFINED 86606 /* Revision ID */
#define FF_DEFINED 86631 /* Revision ID */
#ifdef __cplusplus
extern "C" {
#endif
#include <rtthread.h>
#include "ffconf.h" /* FatFs configuration options */
#if FF_DEFINED != FFCONF_DEF
......@@ -36,10 +35,14 @@ extern "C" {
/* Integer types used for FatFs API */
#if defined(_WIN32) /* Main development platform */
#if defined(_WIN32) /* Windows VC++ (for development only) */
#define FF_INTDEF 2
#include <windows.h>
typedef unsigned __int64 QWORD;
#include <float.h>
#define isnan(v) _isnan(v)
#define isinf(v) (!_finite(v))
#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__cplusplus) /* C99 or later */
#define FF_INTDEF 2
#include <stdint.h>
......@@ -49,6 +52,7 @@ typedef uint16_t WORD; /* 16-bit unsigned integer */
typedef uint32_t DWORD; /* 32-bit unsigned integer */
typedef uint64_t QWORD; /* 64-bit unsigned integer */
typedef WORD WCHAR; /* UTF-16 character type */
#else /* Earlier than C99 */
#define FF_INTDEF 1
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
......@@ -59,28 +63,29 @@ typedef WORD WCHAR; /* UTF-16 character type */
#endif
/* Definitions of volume management */
/* Type of file size and LBA variables */
#if FF_MULTI_PARTITION /* Multiple partition configuration */
typedef struct {
BYTE pd; /* Physical drive number */
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
} PARTITION;
extern PARTITION VolToPart[]; /* Volume - Partition mapping table */
#if FF_FS_EXFAT
#if FF_INTDEF != 2
#error exFAT feature wants C99 or later
#endif
#if FF_STR_VOLUME_ID
#ifndef FF_VOLUME_STRS
extern const char* VolumeStr[FF_VOLUMES]; /* User defied volume ID */
typedef QWORD FSIZE_t;
#if FF_LBA64
typedef QWORD LBA_t;
#else
typedef DWORD LBA_t;
#endif
#else
#if FF_LBA64
#error exFAT needs to be enabled when enable 64-bit LBA
#endif
typedef DWORD FSIZE_t;
typedef DWORD LBA_t;
#endif
/* Type of path name strings on FatFs API */
#ifndef _INC_TCHAR
#define _INC_TCHAR
/* Type of path name strings on FatFs API (TCHAR) */
#if FF_USE_LFN && FF_LFN_UNICODE == 1 /* Unicode in UTF-16 encoding */
typedef WCHAR TCHAR;
......@@ -102,28 +107,22 @@ typedef char TCHAR;
#define _TEXT(x) x
#endif
#endif
/* Definitions of volume management */
/* Type of file size and LBA variables */
#if FF_FS_EXFAT
#if FF_INTDEF != 2
#error exFAT feature wants C99 or later
#endif
typedef QWORD FSIZE_t;
#if FF_LBA64
typedef QWORD LBA_t;
#else
typedef DWORD LBA_t;
#if FF_MULTI_PARTITION /* Multiple partition configuration */
typedef struct {
BYTE pd; /* Physical drive number */
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
} PARTITION;
extern PARTITION VolToPart[]; /* Volume - Partition mapping table */
#endif
#else
#if FF_LBA64
#error exFAT needs to be enabled when enable 64-bit LBA
#if FF_STR_VOLUME_ID
#ifndef FF_VOLUME_STRS
extern const char* VolumeStr[FF_VOLUMES]; /* User defied volume ID */
#endif
typedef DWORD FSIZE_t;
typedef DWORD LBA_t;
#endif
......@@ -347,10 +346,6 @@ TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the fil
#define f_rmdir(path) f_unlink(path)
#define f_unmount(path) f_mount(0, path, 0)
#ifndef EOF
#define EOF (-1)
#endif
......
......@@ -2,7 +2,7 @@
/ FatFs Functional Configurations
/---------------------------------------------------------------------------*/
#define FFCONF_DEF 86606 /* Revision ID */
#define FFCONF_DEF 86631 /* Revision ID */
/*---------------------------------------------------------------------------/
/ Function Configurations
......@@ -25,14 +25,6 @@
/ 3: f_lseek() function is removed in addition to 2. */
#define FF_USE_STRFUNC 0
/* This option switches string functions, f_gets(), f_putc(), f_puts() and f_printf().
/
/ 0: Disable string functions.
/ 1: Enable without LF-CRLF conversion.
/ 2: Enable with LF-CRLF conversion. */
#define FF_USE_FIND 0
/* This option switches filtered directory read functions, f_findfirst() and
/ f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
......@@ -64,15 +56,35 @@
/* This option switches f_forward() function. (0:Disable or 1:Enable) */
#define FF_USE_STRFUNC 0
#define FF_PRINT_LLI 0
#define FF_PRINT_FLOAT 0
#define FF_STRF_ENCODE 3
/* FF_USE_STRFUNC switches string functions, f_gets(), f_putc(), f_puts() and
/ f_printf().
/
/ 0: Disable. FF_PRINT_LLI, FF_PRINT_FLOAT and FF_STRF_ENCODE have no effect.
/ 1: Enable without LF-CRLF conversion.
/ 2: Enable with LF-CRLF conversion.
/
/ FF_PRINT_LLI = 1 makes f_printf() support long long argument and FF_PRINT_FLOAT = 1/2
makes f_printf() support floating point argument. These features want C99 or later.
/ When FF_LFN_UNICODE >= 1 with LFN enabled, string functions convert the character
/ encoding in it. FF_STRF_ENCODE selects assumption of character encoding ON THE FILE
/ to be read/written via those functions.
/
/ 0: ANSI/OEM in current CP
/ 1: Unicode in UTF-16LE
/ 2: Unicode in UTF-16BE
/ 3: Unicode in UTF-8
*/
/*---------------------------------------------------------------------------/
/ Locale and Namespace Configurations
/---------------------------------------------------------------------------*/
#ifdef RT_DFS_ELM_CODE_PAGE
# define FF_CODE_PAGE RT_DFS_ELM_CODE_PAGE
#else
# define FF_CODE_PAGE 936
#endif
#define FF_CODE_PAGE 932
/* This option specifies the OEM code page to be used on the target system.
/ Incorrect code page setting can cause a file open failure.
/
......@@ -101,13 +113,8 @@
*/
#if RT_DFS_ELM_USE_LFN
#define FF_USE_LFN RT_DFS_ELM_USE_LFN
#define FF_MAX_LFN RT_DFS_ELM_MAX_LFN
#else
#define FF_USE_LFN 0 /* 0 to 3 */
#define FF_MAX_LFN 255 /* Maximum LFN length to handle (12 to 255) */
#endif
#define FF_USE_LFN 0
#define FF_MAX_LFN 255
/* The FF_USE_LFN switches the support for LFN (long file name).
/
/ 0: Disable LFN. FF_MAX_LFN has no effect.
......@@ -126,7 +133,7 @@
/ ff_memfree() exemplified in ffsystem.c, need to be added to the project. */
#ifdef RT_DFS_ELM_LFN_UNICODE
#define FF_LFN_UNICODE 0
/* This option switches the character encoding on the API when LFN is enabled.
/
/ 0: ANSI/OEM in current CP (TCHAR = char)
......@@ -136,10 +143,7 @@
/
/ Also behavior of string I/O functions will be affected by this option.
/ When LFN is not enabled, this option has no effect. */
#define FF_LFN_UNICODE RT_DFS_ELM_LFN_UNICODE /* 0:ANSI/OEM or 1:Unicode */
#else
#define FF_LFN_UNICODE 0 /* 0:ANSI/OEM or 1:Unicode */
#endif
#define FF_LFN_BUF 255
#define FF_SFN_BUF 12
......@@ -149,19 +153,6 @@
/ on character encoding. When LFN is not enabled, these options have no effect. */
#define FF_STRF_ENCODE 3
/* When FF_LFN_UNICODE >= 1 with LFN enabled, string I/O functions, f_gets(),
/ f_putc(), f_puts and f_printf() convert the character encoding in it.
/ This option selects assumption of character encoding ON THE FILE to be
/ read/written via those functions.
/
/ 0: ANSI/OEM in current CP
/ 1: Unicode in UTF-16LE
/ 2: Unicode in UTF-16BE
/ 3: Unicode in UTF-8
*/
#define FF_FS_RPATH 0
/* This option configures support for relative path.
/
......@@ -175,11 +166,7 @@
/ Drive/Volume Configurations
/---------------------------------------------------------------------------*/
#ifdef RT_DFS_ELM_DRIVES
#define FF_VOLUMES RT_DFS_ELM_DRIVES
#else
#define FF_VOLUMES 1
#endif
#define FF_VOLUMES 1
/* Number of volumes (logical drives) to be used. (1-10) */
......@@ -206,7 +193,7 @@
/ funciton will be available. */
#define FF_MIN_SS 512
#define FF_MIN_SS 512
#ifdef RT_DFS_ELM_MAX_SECTOR_SIZE
#define FF_MAX_SS RT_DFS_ELM_MAX_SECTOR_SIZE
#else
......@@ -214,7 +201,7 @@
#endif
/* This set of options configures the range of sector size to be supported. (512,
/ 1024, 2048 or 4096) Always set both 512 for most systems, generic memory card and
/ harddisk. But a larger value may be required for on-board flash memory and some
/ harddisk, but a larger value may be required for on-board flash memory and some
/ type of optical media. When FF_MAX_SS is larger than FF_MIN_SS, FatFs is configured
/ for variable sector size mode and disk_ioctl() function needs to implement
/ GET_SECTOR_SIZE command. */
......@@ -225,8 +212,8 @@
/ To enable the 64-bit LBA, also exFAT needs to be enabled. (FF_FS_EXFAT == 1) */
#define FF_MIN_GPT 0x100000000
/* Minimum number of sectors to switch GPT format to create partition in f_mkfs and
#define FF_MIN_GPT 0x10000000
/* Minimum number of sectors to switch GPT as partitioning format in f_mkfs and
/ f_fdisk function. 0x100000000 max. This option has no effect when FF_LBA64 == 0. */
......@@ -247,11 +234,8 @@
/ Instead of private sector buffer eliminated from the file object, common sector
/ buffer in the filesystem object (FATFS) is used for the file data transfer. */
#ifdef RT_DFS_ELM_USE_EXFAT
#define FF_FS_EXFAT 1
#else
#define FF_FS_EXFAT 0
#endif
#define FF_FS_EXFAT 0
/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
/ To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1)
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */
......@@ -260,7 +244,7 @@
#define FF_FS_NORTC 0
#define FF_NORTC_MON 1
#define FF_NORTC_MDAY 1
#define FF_NORTC_YEAR 2019
#define FF_NORTC_YEAR 2020
/* The option FF_FS_NORTC switches timestamp functiton. If the system does not have
/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable
/ the timestamp function. Every object modified by FatFs will have a fixed timestamp
......@@ -294,6 +278,7 @@
/ can be opened simultaneously under file lock control. Note that the file
/ lock control is independent of re-entrancy. */
/* #include <somertos.h> // O/S definitions */
#include <rtdef.h>
#ifdef RT_DFS_ELM_REENTRANT
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册