From 7cde4a9d1ec333f39c002457bb293d7a17e897fc Mon Sep 17 00:00:00 2001 From: Phil Howard Date: Fri, 12 May 2023 14:57:24 +0100 Subject: [PATCH] FatFS: Bump to R0.15. --- drivers/fatfs/00history.txt | 10 + drivers/fatfs/00readme.txt | 2 +- drivers/fatfs/ff.c | 598 +++++++++++++++++++++--------------- drivers/fatfs/ff.h | 69 +++-- drivers/fatfs/ffconf.h | 43 ++- drivers/fatfs/ffsystem.c | 300 ++++++++++-------- drivers/fatfs/ffunicode.c | 44 +-- 7 files changed, 609 insertions(+), 457 deletions(-) diff --git a/drivers/fatfs/00history.txt b/drivers/fatfs/00history.txt index 8a0169b1..7a153a22 100644 --- a/drivers/fatfs/00history.txt +++ b/drivers/fatfs/00history.txt @@ -357,3 +357,13 @@ R0.14b (April 17, 2021) Fixed some compiler warnings. + +R0.15 (November 6, 2022) + Changed user provided synchronization functions in order to completely eliminate the platform dependency from FatFs code. + FF_SYNC_t is removed from the configuration options. + Fixed a potential error in f_mount when FF_FS_REENTRANT. + Fixed file lock control FF_FS_LOCK is not mutal excluded when FF_FS_REENTRANT && FF_VOLUMES > 1 is true. + Fixed f_mkfs() creates broken exFAT volume when the size of volume is >= 2^32 sectors. + Fixed string functions cannot write the unicode characters not in BMP when FF_LFN_UNICODE == 2 (UTF-8). + Fixed a compatibility issue in identification of GPT header. + diff --git a/drivers/fatfs/00readme.txt b/drivers/fatfs/00readme.txt index 4960997b..3de3aeaa 100644 --- a/drivers/fatfs/00readme.txt +++ b/drivers/fatfs/00readme.txt @@ -1,4 +1,4 @@ -FatFs Module Source Files R0.14b +FatFs Module Source Files R0.15 FILES diff --git a/drivers/fatfs/ff.c b/drivers/fatfs/ff.c index d2096058..6d412fa0 100644 --- a/drivers/fatfs/ff.c +++ b/drivers/fatfs/ff.c @@ -1,8 +1,8 @@ /*----------------------------------------------------------------------------/ -/ FatFs - Generic FAT Filesystem Module R0.14b / +/ FatFs - Generic FAT Filesystem Module R0.15 w/patch1 / /-----------------------------------------------------------------------------/ / -/ Copyright (C) 2021, ChaN, all right reserved. +/ Copyright (C) 2022, 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 @@ -30,7 +30,7 @@ ---------------------------------------------------------------------------*/ -#if FF_DEFINED != 86631 /* Revision ID */ +#if FF_DEFINED != 80286 /* Revision ID */ #error Wrong include file (ff.h). #endif @@ -208,26 +208,26 @@ #define PTE_StLba 8 /* MBR PTE: Start in LBA */ #define PTE_SizLba 12 /* MBR PTE: Size in LBA */ -#define GPTH_Sign 0 /* GPT: Header signature (8-byte) */ -#define GPTH_Rev 8 /* GPT: Revision (DWORD) */ -#define GPTH_Size 12 /* GPT: Header size (DWORD) */ -#define GPTH_Bcc 16 /* GPT: Header BCC (DWORD) */ -#define GPTH_CurLba 24 /* GPT: Main header LBA (QWORD) */ -#define GPTH_BakLba 32 /* GPT: Backup header LBA (QWORD) */ -#define GPTH_FstLba 40 /* GPT: First LBA for partitions (QWORD) */ -#define GPTH_LstLba 48 /* GPT: Last LBA for partitions (QWORD) */ -#define GPTH_DskGuid 56 /* GPT: Disk GUID (16-byte) */ -#define GPTH_PtOfs 72 /* GPT: Partation table LBA (QWORD) */ -#define GPTH_PtNum 80 /* GPT: Number of table entries (DWORD) */ -#define GPTH_PteSize 84 /* GPT: Size of table entry (DWORD) */ -#define GPTH_PtBcc 88 /* GPT: Partation table BCC (DWORD) */ -#define SZ_GPTE 128 /* GPT: Size of partition table entry */ +#define GPTH_Sign 0 /* GPT HDR: Signature (8-byte) */ +#define GPTH_Rev 8 /* GPT HDR: Revision (DWORD) */ +#define GPTH_Size 12 /* GPT HDR: Header size (DWORD) */ +#define GPTH_Bcc 16 /* GPT HDR: Header BCC (DWORD) */ +#define GPTH_CurLba 24 /* GPT HDR: This header LBA (QWORD) */ +#define GPTH_BakLba 32 /* GPT HDR: Another header LBA (QWORD) */ +#define GPTH_FstLba 40 /* GPT HDR: First LBA for partition data (QWORD) */ +#define GPTH_LstLba 48 /* GPT HDR: Last LBA for partition data (QWORD) */ +#define GPTH_DskGuid 56 /* GPT HDR: Disk GUID (16-byte) */ +#define GPTH_PtOfs 72 /* GPT HDR: Partition table LBA (QWORD) */ +#define GPTH_PtNum 80 /* GPT HDR: Number of table entries (DWORD) */ +#define GPTH_PteSize 84 /* GPT HDR: Size of table entry (DWORD) */ +#define GPTH_PtBcc 88 /* GPT HDR: Partition table BCC (DWORD) */ +#define SZ_GPTE 128 /* GPT PTE: Size of partition table entry */ #define GPTE_PtGuid 0 /* GPT PTE: Partition type GUID (16-byte) */ #define GPTE_UpGuid 16 /* GPT PTE: Partition unique GUID (16-byte) */ -#define GPTE_FstLba 32 /* GPT PTE: First LBA (QWORD) */ -#define GPTE_LstLba 40 /* GPT PTE: Last LBA inclusive (QWORD) */ -#define GPTE_Flags 48 /* GPT PTE: Flags (QWORD) */ -#define GPTE_Name 56 /* GPT PTE: Name */ +#define GPTE_FstLba 32 /* GPT PTE: First LBA of partition (QWORD) */ +#define GPTE_LstLba 40 /* GPT PTE: Last LBA of partition (QWORD) */ +#define GPTE_Flags 48 /* GPT PTE: Partition flags (QWORD) */ +#define GPTE_Name 56 /* GPT PTE: Partition name */ /* Post process on fatal error in the file operations */ @@ -239,7 +239,7 @@ #if FF_USE_LFN == 1 #error Static LFN work area cannot be used in thread-safe configuration #endif -#define LEAVE_FF(fs, res) { unlock_fs(fs, res); return res; } +#define LEAVE_FF(fs, res) { unlock_volume(fs, res); return res; } #else #define LEAVE_FF(fs, res) return res #endif @@ -278,15 +278,15 @@ /* File lock controls */ -#if FF_FS_LOCK != 0 +#if FF_FS_LOCK #if FF_FS_READONLY #error FF_FS_LOCK must be 0 at read-only configuration #endif typedef struct { - FATFS *fs; /* Object ID 1, volume (NULL:blank entry) */ + FATFS* fs; /* Object ID 1, volume (NULL:blank entry) */ DWORD clu; /* Object ID 2, containing directory (0:root) */ DWORD ofs; /* Object ID 3, offset in the directory */ - WORD ctr; /* Object open counter, 0:none, 0x01..0xFF:read mode open count, 0x100:write mode */ + UINT ctr; /* Object open counter, 0:none, 0x01..0xFF:read mode open count, 0x100:write mode */ } FILESEM; #endif @@ -461,20 +461,23 @@ typedef struct { #if FF_VOLUMES < 1 || FF_VOLUMES > 10 #error Wrong FF_VOLUMES setting #endif -static FATFS* FatFs[FF_VOLUMES]; /* Pointer to the filesystem objects (logical drives) */ +static FATFS *FatFs[FF_VOLUMES]; /* Pointer to the filesystem objects (logical drives) */ static WORD Fsid; /* Filesystem mount ID */ #if FF_FS_RPATH != 0 -static BYTE CurrVol; /* Current drive */ +static BYTE CurrVol; /* Current drive set by f_chdrive() */ #endif #if FF_FS_LOCK != 0 static FILESEM Files[FF_FS_LOCK]; /* Open object lock semaphores */ +#if FF_FS_REENTRANT +static BYTE SysLock; /* System lock flag (0:no mutex, 1:unlocked, 2:locked) */ +#endif #endif #if FF_STR_VOLUME_ID #ifdef FF_VOLUME_STRS -static const char* const VolumeStr[FF_VOLUMES] = {FF_VOLUME_STRS}; /* Pre-defined volume ID */ +static const char *const VolumeStr[FF_VOLUMES] = {FF_VOLUME_STRS}; /* Pre-defined volume ID */ #endif #endif @@ -563,7 +566,8 @@ static WCHAR LfnBuf[FF_MAX_LFN + 1]; /* LFN working buffer */ #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 */ +static const BYTE* ExCvt; /* Ptr to SBCS up-case table Ct???[] (null:not used) */ +static const BYTE* DbcTbl; /* Ptr to DBCS code range table Dc???[] (null:not used) */ static const BYTE Ct437[] = TBL_CT437; static const BYTE Ct720[] = TBL_CT720; @@ -887,21 +891,45 @@ static UINT put_utf ( /* Returns number of encoding units written (0:buffer over /*-----------------------------------------------------------------------*/ /* Request/Release grant to access the volume */ /*-----------------------------------------------------------------------*/ -static int lock_fs ( /* 1:Ok, 0:timeout */ - FATFS* fs /* Filesystem object */ + +static int lock_volume ( /* 1:Ok, 0:timeout */ + FATFS* fs, /* Filesystem object to lock */ + int syslock /* System lock required */ ) { - return ff_req_grant(fs->sobj); + int rv; + + +#if FF_FS_LOCK + rv = ff_mutex_take(fs->ldrv); /* Lock the volume */ + if (rv && syslock) { /* System lock reqiered? */ + rv = ff_mutex_take(FF_VOLUMES); /* Lock the system */ + if (rv) { + SysLock = 2; /* System lock succeeded */ + } else { + ff_mutex_give(fs->ldrv); /* Failed system lock */ + } + } +#else + rv = syslock ? ff_mutex_take(fs->ldrv) : ff_mutex_take(fs->ldrv); /* Lock the volume (this is to prevent compiler warning) */ +#endif + return rv; } -static void unlock_fs ( +static void unlock_volume ( FATFS* fs, /* Filesystem object */ FRESULT res /* Result code to be returned */ ) { if (fs && res != FR_NOT_ENABLED && res != FR_INVALID_DRIVE && res != FR_TIMEOUT) { - ff_rel_grant(fs->sobj); +#if FF_FS_LOCK + if (SysLock == 2) { /* Is the system locked? */ + SysLock = 1; + ff_mutex_give(FF_VOLUMES); + } +#endif + ff_mutex_give(fs->ldrv); /* Unlock the volume */ } } @@ -909,12 +937,12 @@ static void unlock_fs ( -#if FF_FS_LOCK != 0 +#if FF_FS_LOCK /*-----------------------------------------------------------------------*/ -/* File lock control functions */ +/* File shareing control functions */ /*-----------------------------------------------------------------------*/ -static FRESULT chk_lock ( /* Check if the file can be accessed */ +static FRESULT chk_share ( /* Check if the file can be accessed */ DIR* dp, /* Directory object pointing the file to be checked */ int acc /* Desired access type (0:Read mode open, 1:Write mode open, 2:Delete or rename) */ ) @@ -941,16 +969,16 @@ static FRESULT chk_lock ( /* Check if the file can be accessed */ } -static int enq_lock (void) /* Check if an entry is available for a new object */ +static int enq_share (void) /* Check if an entry is available for a new object */ { UINT i; - for (i = 0; i < FF_FS_LOCK && Files[i].fs; i++) ; + for (i = 0; i < FF_FS_LOCK && Files[i].fs; i++) ; /* Find a free entry */ return (i == FF_FS_LOCK) ? 0 : 1; } -static UINT inc_lock ( /* Increment object open counter and returns its index (0:Internal error) */ +static UINT inc_share ( /* Increment object open counter and returns its index (0:Internal error) */ DIR* dp, /* Directory object pointing the file to register or increment */ int acc /* Desired access (0:Read, 1:Write, 2:Delete/Rename) */ ) @@ -965,7 +993,7 @@ static UINT inc_lock ( /* Increment object open counter and returns its index (0 } if (i == FF_FS_LOCK) { /* Not opened. Register it as new. */ - for (i = 0; i < FF_FS_LOCK && Files[i].fs; i++) ; + for (i = 0; i < FF_FS_LOCK && Files[i].fs; i++) ; /* Find a free entry */ if (i == FF_FS_LOCK) return 0; /* No free entry to register (int err) */ Files[i].fs = dp->obj.fs; Files[i].clu = dp->obj.sclust; @@ -981,30 +1009,32 @@ static UINT inc_lock ( /* Increment object open counter and returns its index (0 } -static FRESULT dec_lock ( /* Decrement object open counter */ +static FRESULT dec_share ( /* Decrement object open counter */ UINT i /* Semaphore index (1..) */ ) { - WORD n; + UINT n; FRESULT res; 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 == 0x100) n = 0; /* If write mode open, delete the object semaphore */ 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 */ + if (n == 0) { /* Delete the object semaphore if open count becomes zero */ + Files[i].fs = 0; /* Free the entry << 1, there is a potential error in this process >>> */ + } res = FR_OK; } else { - res = FR_INT_ERR; /* Invalid index nunber */ + res = FR_INT_ERR; /* Invalid index number */ } return res; } -static void clear_lock ( /* Clear lock entries of the volume */ - FATFS *fs +static void clear_share ( /* Clear all lock entries of the volume */ + FATFS* fs ) { UINT i; @@ -1014,7 +1044,7 @@ static void clear_lock ( /* Clear lock entries of the volume */ } } -#endif /* FF_FS_LOCK != 0 */ +#endif /* FF_FS_LOCK */ @@ -1599,7 +1629,8 @@ static DWORD clmt_clust ( /* <2:Error, >=2:Cluster number */ FSIZE_t ofs /* File offset to be converted to cluster# */ ) { - DWORD cl, ncl, *tbl; + DWORD cl, ncl; + DWORD *tbl; FATFS *fs = fp->obj.fs; @@ -1990,7 +2021,7 @@ static void gen_numname ( seq = (UINT)sreg; } - /* Make suffix (~ + hexdecimal) */ + /* Make suffix (~ + hexadecimal) */ i = 7; do { c = (BYTE)((seq % 16) + '0'); seq /= 16; @@ -2092,17 +2123,17 @@ static DWORD xsum32 ( /* Returns 32-bit checksum */ -/*-----------------------------------*/ -/* exFAT: Get a directry entry block */ -/*-----------------------------------*/ +/*------------------------------------*/ +/* exFAT: Get a directory entry block */ +/*------------------------------------*/ static FRESULT load_xdir ( /* FR_INT_ERR: invalid entry block */ - DIR* dp /* Reading direcotry object pointing top of the entry block to load */ + DIR* dp /* Reading directory object pointing top of the entry block to load */ ) { 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 directory entry block 85+C0+C1s */ /* Load file directory entry */ @@ -2166,7 +2197,7 @@ static void init_alloc_info ( /*------------------------------------------------*/ static FRESULT load_obj_xdir ( - DIR* dp, /* Blank directory object to be used to access containing direcotry */ + DIR* dp, /* Blank directory object to be used to access containing directory */ const FFOBJID* obj /* Object with its containing directory information */ ) { @@ -2195,18 +2226,18 @@ static FRESULT load_obj_xdir ( /*----------------------------------------*/ static FRESULT store_xdir ( - DIR* dp /* Pointer to the direcotry object */ + DIR* dp /* Pointer to the directory object */ ) { 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 directory entry block 85+C0+C1s */ /* Create set sum */ st_word(dirb + XDIR_SetSum, xdir_sum(dirb)); nent = dirb[XDIR_NumSec] + 1; - /* Store the direcotry entry block to the directory */ + /* Store the directory entry block to the directory */ res = dir_sdi(dp, dp->blk_ofs); while (res == FR_OK) { res = move_window(dp->obj.fs, dp->sect); @@ -2223,11 +2254,11 @@ static FRESULT store_xdir ( /*-------------------------------------------*/ -/* exFAT: Create a new directory enrty block */ +/* exFAT: Create a new directory entry block */ /*-------------------------------------------*/ static void create_xdir ( - BYTE* dirb, /* Pointer to the direcotry entry block buffer */ + BYTE* dirb, /* Pointer to the directory entry block buffer */ const WCHAR* lfn /* Pointer to the object name */ ) { @@ -2610,19 +2641,23 @@ static void get_fileinfo ( 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 */ + if (si >= MAXDIRB(FF_MAX_LFN)) { /* Truncated directory block? */ + di = 0; break; + } + 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 */ + 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? */ + if (nw == 0) { /* Buffer overflow or wrong char? */ + di = 0; break; + } di += nw; hs = 0; } if (hs != 0) di = 0; /* Broken surrogate pair? */ - if (di == 0) fno->fname[di++] = '?'; /* Inaccessible object name? */ + 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 */ @@ -2643,7 +2678,9 @@ static void get_fileinfo ( 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? */ + if (nw == 0) { /* Buffer overflow or wrong char? */ + di = 0; break; + } di += nw; hs = 0; } @@ -2663,9 +2700,13 @@ static void get_fileinfo ( wc = wc << 8 | dp->dir[si++]; } wc = ff_oem2uni(wc, CODEPAGE); /* ANSI/OEM -> Unicode */ - if (wc == 0) { di = 0; break; } /* Wrong char in the current code page? */ + if (wc == 0) { /* Wrong char in the current code page? */ + di = 0; break; + } nw = put_utf(wc, &fno->altname[di], FF_SFN_BUF - di); /* Store it in API encoding */ - if (nw == 0) { di = 0; break; } /* Buffer overflow? */ + if (nw == 0) { /* Buffer overflow? */ + di = 0; break; + } di += nw; #else /* ANSI/OEM output */ fno->altname[di++] = (TCHAR)wc; /* Store it without any conversion */ @@ -2674,8 +2715,8 @@ static void get_fileinfo ( fno->altname[di] = 0; /* Terminate the SFN (null string means SFN is invalid) */ if (fno->fname[0] == 0) { /* If LFN is invalid, altname[] needs to be copied to fname[] */ - if (di == 0) { /* If LFN and SFN both are invalid, this object is inaccesible */ - fno->fname[di++] = '?'; + if (di == 0) { /* If LFN and SFN both are invalid, this object is inaccessible */ + fno->fname[di++] = '\?'; } else { for (si = di = 0, lcf = NS_BODY; fno->altname[si]; si++, di++) { /* Copy altname[] to fname[] with case information */ wc = (WCHAR)fno->altname[si]; @@ -2756,7 +2797,8 @@ static int pattern_match ( /* 0:mismatched, 1:matched */ UINT recur /* Recursion count */ ) { - const TCHAR *pptr, *nptr; + const TCHAR *pptr; + const TCHAR *nptr; DWORD pchr, nchr; UINT sk; @@ -2770,12 +2812,16 @@ static int pattern_match ( /* 0:mismatched, 1:matched */ do { pptr = pat; nptr = nam; /* Top of pattern and name to match */ for (;;) { - if (*pptr == '?' || *pptr == '*') { /* Wildcard term? */ + 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 (*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 */ } @@ -2805,10 +2851,11 @@ static FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not cr { #if FF_USE_LFN /* LFN configuration */ BYTE b, cf; - WCHAR wc, *lfn; + WCHAR wc; + WCHAR *lfn; + const TCHAR* p; DWORD uc; UINT i, ni, si, di; - const TCHAR *p; /* Create LFN into LFN working buffer */ @@ -2930,7 +2977,8 @@ static FRESULT create_name ( /* FR_OK: successful, FR_INVALID_NAME: could not cr #else /* FF_USE_LFN : Non-LFN configuration */ - BYTE c, d, *sfn; + BYTE c, d; + BYTE *sfn; UINT ni, si, i; const char *p; @@ -3091,7 +3139,8 @@ static int get_ldnumber ( /* Returns logical drive number (-1:invalid drive numb const TCHAR** path /* Pointer to pointer to the path name */ ) { - const TCHAR *tp, *tt; + const TCHAR *tp; + const TCHAR *tt; TCHAR tc; int i; int vol = -1; @@ -3102,7 +3151,9 @@ 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 (!IsTerminator(tc) && tc != ':'); /* Find a colon in the path */ + do { /* Find a colon in the path */ + tc = *tt++; + } while (!IsTerminator(tc) && tc != ':'); if (tc == ':') { /* DOS/Windows style volume ID? */ i = FF_VOLUMES; @@ -3190,16 +3241,18 @@ static int test_gpt_header ( /* 0:Invalid, 1:Valid */ ) { UINT i; - DWORD bcc; + DWORD bcc, hlen; - 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 */ + if (memcmp(gpth + GPTH_Sign, "EFI PART" "\0\0\1", 12)) return 0; /* Check signature and version (1.0) */ + hlen = ld_dword(gpth + GPTH_Size); /* Check header size */ + if (hlen < 92 || hlen > FF_MIN_SS) return 0; + for (i = 0, bcc = 0xFFFFFFFF; i < hlen; i++) { /* Check header BCC */ bcc = crc32(bcc, i - GPTH_Bcc < 4 ? 0 : gpth[i]); } if (~bcc != ld_dword(gpth + GPTH_Bcc)) return 0; if (ld_dword(gpth + GPTH_PteSize) != SZ_GPTE) return 0; /* Table entry size (must be SZ_GPTE bytes) */ - if (ld_dword(gpth + GPTH_PtNum) > 128) return 0; /* Table size (must be 128 entries or less) */ + if (ld_dword(gpth + GPTH_PtNum) > 128) return 0; /* Table size (must be 128 entries or less) */ return 1; } @@ -3209,7 +3262,7 @@ static int test_gpt_header ( /* 0:Invalid, 1:Valid */ /* Generate random value */ static DWORD make_rand ( DWORD seed, /* Seed value */ - BYTE* buff, /* Output buffer */ + BYTE *buff, /* Output buffer */ UINT n /* Data length */ ) { @@ -3277,7 +3330,7 @@ static UINT check_fs ( /* 0:FAT/FAT32 VBR, 1:exFAT VBR, 2:Not FAT and valid BS, static UINT find_volume ( /* Returns BS status found in the hosting drive */ FATFS* fs, /* Filesystem object */ - UINT part /* Partition to fined = 0:auto, 1..:forced */ + UINT part /* Partition to fined = 0:find as SFD and partitions, >0:forced partition number */ ) { UINT fmt, i; @@ -3332,15 +3385,15 @@ static UINT find_volume ( /* Returns BS status found in the hosting drive */ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */ const TCHAR** path, /* Pointer to pointer to the path name (drive number) */ FATFS** rfs, /* Pointer to pointer to the found filesystem object */ - BYTE mode /* !=0: Check write protection for write access */ + BYTE mode /* Desiered access mode to check write protection */ ) { int vol; + FATFS *fs; DSTATUS stat; LBA_t bsect; DWORD tsect, sysect, fasize, nclst, szbfat; WORD nrsv; - FATFS *fs; UINT fmt; @@ -3353,7 +3406,7 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */ fs = FatFs[vol]; /* Get pointer to the filesystem object */ if (!fs) return FR_NOT_ENABLED; /* Is the filesystem object available? */ #if FF_FS_REENTRANT - if (!lock_fs(fs)) return FR_TIMEOUT; /* Lock the volume */ + if (!lock_volume(fs, 1)) return FR_TIMEOUT; /* Lock the volume, and system if needed */ #endif *rfs = fs; /* Return pointer to the filesystem object */ @@ -3371,9 +3424,8 @@ 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 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 */ - stat = disk_initialize(fs->pdrv); /* Initialize the physical drive */ + fs->fs_type = 0; /* Invalidate the filesystem object */ + stat = disk_initialize(fs->pdrv); /* Initialize the volume hosting physical drive */ if (stat & STA_NOINIT) { /* Check if the initialization succeeded */ return FR_NOT_READY; /* Failed to initialize due to no medium or hard error */ } @@ -3385,11 +3437,11 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */ if (SS(fs) > FF_MAX_SS || SS(fs) < FF_MIN_SS || (SS(fs) & (SS(fs) - 1))) return FR_DISK_ERR; #endif - /* Find an FAT volume on the drive */ + /* Find an FAT volume on the hosting drive */ fmt = find_volume(fs, LD2PT(vol)); - if (fmt == 4) return FR_DISK_ERR; /* An error occured in the disk I/O layer */ + if (fmt == 4) return FR_DISK_ERR; /* An error occurred in the disk I/O layer */ if (fmt >= 2) return FR_NO_FILESYSTEM; /* No FAT volume is found */ - bsect = fs->winsect; /* Volume offset */ + bsect = fs->winsect; /* Volume offset in the hosting physical drive */ /* An FAT volume is found (bsect). Following code initializes the filesystem object */ @@ -3426,7 +3478,7 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */ fs->volbase = bsect; fs->database = bsect + ld_dword(fs->win + BPB_DataOfsEx); fs->fatbase = bsect + ld_dword(fs->win + BPB_FatOfsEx); - if (maxlba < (QWORD)fs->database + nclst * fs->csize) return FR_NO_FILESYSTEM; /* (Volume size must not be smaller than the size requiered) */ + if (maxlba < (QWORD)fs->database + nclst * fs->csize) return FR_NO_FILESYSTEM; /* (Volume size must not be smaller than the size required) */ fs->dirbase = ld_dword(fs->win + BPB_RootClusEx); /* Get bitmap location and check if it is contiguous (implementation assumption) */ @@ -3447,7 +3499,7 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */ if (move_window(fs, fs->fatbase + bcl / (SS(fs) / 4)) != FR_OK) return FR_DISK_ERR; cv = ld_dword(fs->win + bcl % (SS(fs) / 4) * 4); if (cv == 0xFFFFFFFF) break; /* Last link? */ - if (cv != ++bcl) return FR_NO_FILESYSTEM; /* Fragmented? */ + if (cv != ++bcl) return FR_NO_FILESYSTEM; /* Fragmented bitmap? */ } #if !FF_FS_READONLY @@ -3534,7 +3586,7 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */ #endif /* !FF_FS_READONLY */ } - fs->fs_type = (BYTE)fmt;/* FAT sub-type */ + fs->fs_type = (BYTE)fmt;/* FAT sub-type (the filesystem object gets valid) */ fs->id = ++Fsid; /* Volume mount ID */ #if FF_USE_LFN == 1 fs->lfnbuf = LfnBuf; /* Static LFN working buffer */ @@ -3545,8 +3597,8 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */ #if FF_FS_RPATH != 0 fs->cdir = 0; /* Initialize current directory */ #endif -#if FF_FS_LOCK != 0 /* Clear file lock semaphores */ - clear_lock(fs); +#if FF_FS_LOCK /* Clear file lock semaphores */ + clear_share(fs); #endif return FR_OK; } @@ -3559,7 +3611,7 @@ static FRESULT mount_volume ( /* FR_OK(0): successful, !=0: an error occurred */ /*-----------------------------------------------------------------------*/ static FRESULT validate ( /* Returns FR_OK or FR_INVALID_OBJECT */ - FFOBJID* obj, /* Pointer to the FFOBJID, the 1st member in the FIL/DIR object, to check validity */ + FFOBJID* obj, /* Pointer to the FFOBJID, the 1st member in the FIL/DIR structure, to check validity */ FATFS** rfs /* Pointer to pointer to the owner filesystem object to return */ ) { @@ -3568,22 +3620,22 @@ static FRESULT validate ( /* Returns FR_OK or FR_INVALID_OBJECT */ if (obj && obj->fs && obj->fs->fs_type && obj->id == obj->fs->id) { /* Test if the object is valid */ #if FF_FS_REENTRANT - if (lock_fs(obj->fs)) { /* Obtain the filesystem object */ - if (!(disk_status(obj->fs->pdrv) & STA_NOINIT)) { /* Test if the phsical drive is kept initialized */ + if (lock_volume(obj->fs, 0)) { /* Take a grant to access the volume */ + if (!(disk_status(obj->fs->pdrv) & STA_NOINIT)) { /* Test if the hosting phsical drive is kept initialized */ res = FR_OK; } else { - unlock_fs(obj->fs, FR_OK); + unlock_volume(obj->fs, FR_OK); /* Invalidated volume, abort to access */ } - } else { + } else { /* Could not take */ res = FR_TIMEOUT; } #else - if (!(disk_status(obj->fs->pdrv) & STA_NOINIT)) { /* Test if the phsical drive is kept initialized */ + if (!(disk_status(obj->fs->pdrv) & STA_NOINIT)) { /* Test if the hosting phsical drive is kept initialized */ res = FR_OK; } #endif } - *rfs = (res == FR_OK) ? obj->fs : 0; /* Corresponding filesystem object */ + *rfs = (res == FR_OK) ? obj->fs : 0; /* Return corresponding filesystem object if it is valid */ return res; } @@ -3614,30 +3666,42 @@ FRESULT f_mount ( const TCHAR *rp = path; - /* Get logical drive number */ + /* Get volume ID (logical drive number) */ vol = get_ldnumber(&rp); if (vol < 0) return FR_INVALID_DRIVE; - cfs = FatFs[vol]; /* Pointer to fs object */ + cfs = FatFs[vol]; /* Pointer to the filesystem object of the volume */ - if (cfs) { -#if FF_FS_LOCK != 0 - clear_lock(cfs); + if (cfs) { /* Unregister current filesystem object if regsitered */ + FatFs[vol] = 0; +#if FF_FS_LOCK + clear_share(cfs); #endif -#if FF_FS_REENTRANT /* Discard sync object of the current volume */ - if (!ff_del_syncobj(cfs->sobj)) return FR_INT_ERR; +#if FF_FS_REENTRANT /* Discard mutex of the current volume */ + ff_mutex_delete(vol); #endif - cfs->fs_type = 0; /* Clear old fs object */ + cfs->fs_type = 0; /* Invalidate the filesystem object to be unregistered */ } - if (fs) { - fs->fs_type = 0; /* Clear new fs object */ -#if FF_FS_REENTRANT /* Create sync object for the new volume */ - if (!ff_cre_syncobj((BYTE)vol, &fs->sobj)) return FR_INT_ERR; + if (fs) { /* Register new filesystem object */ + fs->pdrv = LD2PD(vol); /* Volume hosting physical drive */ +#if FF_FS_REENTRANT /* Create a volume mutex */ + fs->ldrv = (BYTE)vol; /* Owner volume ID */ + if (!ff_mutex_create(vol)) return FR_INT_ERR; +#if FF_FS_LOCK + if (SysLock == 0) { /* Create a system mutex if needed */ + if (!ff_mutex_create(FF_VOLUMES)) { + ff_mutex_delete(vol); + return FR_INT_ERR; + } + SysLock = 1; /* System mutex is ready */ + } #endif +#endif + fs->fs_type = 0; /* Invalidate the new filesystem object */ + FatFs[vol] = fs; /* Register new fs object */ } - FatFs[vol] = fs; /* Register new fs object */ - if (opt == 0) return FR_OK; /* Do not mount now, it will be mounted later */ + if (opt == 0) return FR_OK; /* Do not mount now, it will be mounted in subsequent file functions */ res = mount_volume(&path, &fs, 0); /* Force mounted the volume */ LEAVE_FF(fs, res); @@ -3681,9 +3745,9 @@ FRESULT f_open ( if (dj.fn[NSFLAG] & NS_NONAME) { /* Origin directory itself? */ res = FR_INVALID_NAME; } -#if FF_FS_LOCK != 0 +#if FF_FS_LOCK else { - res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0); /* Check if the file can be used */ + res = chk_share(&dj, (mode & ~FA_READ) ? 1 : 0); /* Check if the file can be used */ } #endif } @@ -3691,8 +3755,8 @@ FRESULT f_open ( if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) { if (res != FR_OK) { /* No file, create new */ if (res == FR_NO_FILE) { /* There is no file to open, create a new entry */ -#if FF_FS_LOCK != 0 - res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES; +#if FF_FS_LOCK + res = enq_share() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES; #else res = dir_register(&dj); #endif @@ -3761,8 +3825,8 @@ FRESULT f_open ( if (mode & FA_CREATE_ALWAYS) mode |= FA_MODIFIED; /* Set file change flag if created or overwritten */ fp->dir_sect = fs->winsect; /* Pointer to the directory entry */ fp->dir_ptr = dj.dir; -#if FF_FS_LOCK != 0 - fp->obj.lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0); /* Lock the file for this session */ +#if FF_FS_LOCK + fp->obj.lockid = inc_share(&dj, (mode & ~FA_READ) ? 1 : 0); /* Lock the file for this session */ if (fp->obj.lockid == 0) res = FR_INT_ERR; #endif } @@ -3825,8 +3889,8 @@ 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 */ +#if FF_FS_LOCK + if (res != FR_OK) dec_share(fp->obj.lockid); /* Decrement file open counter if seek failed */ #endif } #endif @@ -3921,7 +3985,7 @@ FRESULT f_read ( fp->flag &= (BYTE)~FA_DIRTY; } #endif - if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */ + if (disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR); /* Fill sector cache */ } #endif fp->sect = sect; @@ -4163,14 +4227,14 @@ FRESULT f_close ( { res = validate(&fp->obj, &fs); /* Lock volume */ if (res == FR_OK) { -#if FF_FS_LOCK != 0 - res = dec_lock(fp->obj.lockid); /* Decrement file open counter */ +#if FF_FS_LOCK + res = dec_share(fp->obj.lockid); /* Decrement file open counter */ if (res == FR_OK) fp->obj.fs = 0; /* Invalidate file object */ #else fp->obj.fs = 0; /* Invalidate file object */ #endif #if FF_FS_REENTRANT - unlock_fs(fs, FR_OK); /* Unlock volume */ + unlock_volume(fs, FR_OK); /* Unlock volume */ #endif } } @@ -4344,7 +4408,9 @@ FRESULT f_getcwd ( #endif /* Add current directory path */ if (res == FR_OK) { - do *tp++ = buff[i++]; while (i < len); /* Copy stacked path string */ + do { /* Copy stacked path string */ + *tp++ = buff[i++]; + } while (i < len); } } FREE_NAMBUF(); @@ -4551,7 +4617,7 @@ FRESULT f_opendir ( if (dp->obj.attr & AM_DIR) { /* This object is a sub-directory */ #if FF_FS_EXFAT if (fs->fs_type == FS_EXFAT) { - dp->obj.c_scl = dp->obj.sclust; /* Get containing directory inforamation */ + dp->obj.c_scl = dp->obj.sclust; /* Get containing directory inforamation */ dp->obj.c_size = ((DWORD)dp->obj.objsize & 0xFFFFFF00) | dp->obj.stat; dp->obj.c_ofs = dp->blk_ofs; init_alloc_info(fs, &dp->obj); /* Get object allocation info */ @@ -4567,10 +4633,10 @@ FRESULT f_opendir ( if (res == FR_OK) { dp->obj.id = fs->id; res = dir_sdi(dp, 0); /* Rewind directory */ -#if FF_FS_LOCK != 0 +#if FF_FS_LOCK if (res == FR_OK) { if (dp->obj.sclust != 0) { - dp->obj.lockid = inc_lock(dp, 0); /* Lock the sub directory */ + dp->obj.lockid = inc_share(dp, 0); /* Lock the sub directory */ if (!dp->obj.lockid) res = FR_TOO_MANY_OPEN_FILES; } else { dp->obj.lockid = 0; /* Root directory need not to be locked */ @@ -4582,7 +4648,7 @@ FRESULT f_opendir ( FREE_NAMBUF(); if (res == FR_NO_FILE) res = FR_NO_PATH; } - if (res != FR_OK) dp->obj.fs = 0; /* Invalidate the directory object if function faild */ + if (res != FR_OK) dp->obj.fs = 0; /* Invalidate the directory object if function failed */ LEAVE_FF(fs, res); } @@ -4604,14 +4670,14 @@ FRESULT f_closedir ( res = validate(&dp->obj, &fs); /* Check validity of the file object */ if (res == FR_OK) { -#if FF_FS_LOCK != 0 - if (dp->obj.lockid) res = dec_lock(dp->obj.lockid); /* Decrement sub-directory open counter */ +#if FF_FS_LOCK + if (dp->obj.lockid) res = dec_share(dp->obj.lockid); /* Decrement sub-directory open counter */ if (res == FR_OK) dp->obj.fs = 0; /* Invalidate directory object */ #else dp->obj.fs = 0; /* Invalidate directory object */ #endif #if FF_FS_REENTRANT - unlock_fs(fs, FR_OK); /* Unlock volume */ + unlock_volume(fs, FR_OK); /* Unlock volume */ #endif } return res; @@ -4637,7 +4703,7 @@ FRESULT f_readdir ( res = validate(&dp->obj, &fs); /* Check validity of the directory object */ if (res == FR_OK) { if (!fno) { - res = dir_sdi(dp, 0); /* Rewind the directory object */ + res = dir_sdi(dp, 0); /* Rewind the directory object */ } else { INIT_NAMBUF(fs); res = DIR_READ_FILE(dp); /* Read an item */ @@ -4775,8 +4841,12 @@ FRESULT f_getfree ( clst = 2; obj.fs = fs; do { stat = get_fat(&obj, clst); - if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } - if (stat == 1) { res = FR_INT_ERR; break; } + if (stat == 0xFFFFFFFF) { + res = FR_DISK_ERR; break; + } + if (stat == 1) { + res = FR_INT_ERR; break; + } if (stat == 0) nfree++; } while (++clst < fs->n_fatent); } else { @@ -4789,12 +4859,12 @@ FRESULT f_getfree ( sect = fs->bitbase; /* Bitmap sector */ i = 0; /* Offset in the sector */ do { /* Counts numbuer of bits with zero in the bitmap */ - if (i == 0) { + if (i == 0) { /* New sector? */ res = move_window(fs, sect++); if (res != FR_OK) break; } - for (b = 8, bm = fs->win[i]; b && clst; b--, clst--) { - if (!(bm & 1)) nfree++; + for (b = 8, bm = ~fs->win[i]; b && clst; b--, clst--) { + nfree += bm & 1; bm >>= 1; } i = (i + 1) % SS(fs); @@ -4806,7 +4876,7 @@ FRESULT f_getfree ( sect = fs->fatbase; /* Top of the FAT */ i = 0; /* Offset in the sector */ do { /* Counts numbuer of entries with zero in the FAT */ - if (i == 0) { + if (i == 0) { /* New sector? */ res = move_window(fs, sect++); if (res != FR_OK) break; } @@ -4894,9 +4964,9 @@ FRESULT f_unlink ( ) { FRESULT res; + FATFS *fs; DIR dj, sdj; DWORD dclst = 0; - FATFS *fs; #if FF_FS_EXFAT FFOBJID obj; #endif @@ -4912,8 +4982,8 @@ FRESULT f_unlink ( if (FF_FS_RPATH && res == FR_OK && (dj.fn[NSFLAG] & NS_DOT)) { res = FR_INVALID_NAME; /* Cannot remove dot entry */ } -#if FF_FS_LOCK != 0 - if (res == FR_OK) res = chk_lock(&dj, 2); /* Check if it is an open object */ +#if FF_FS_LOCK + if (res == FR_OK) res = chk_share(&dj, 2); /* Check if it is an open object */ #endif if (res == FR_OK) { /* The object is accessible */ if (dj.fn[NSFLAG] & NS_NONAME) { @@ -4988,9 +5058,9 @@ FRESULT f_mkdir ( ) { FRESULT res; + FATFS *fs; DIR dj; FFOBJID sobj; - FATFS *fs; DWORD dcl, pcl, tm; DEF_NAMBUF @@ -5073,8 +5143,8 @@ FRESULT f_rename ( ) { FRESULT res; - DIR djo, djn; FATFS *fs; + DIR djo, djn; BYTE buf[FF_FS_EXFAT ? SZDIRE * 2 : SZDIRE], *dir; LBA_t sect; DEF_NAMBUF @@ -5087,9 +5157,9 @@ FRESULT f_rename ( INIT_NAMBUF(fs); 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 FF_FS_LOCK if (res == FR_OK) { - res = chk_lock(&djo, 2); + res = chk_share(&djo, 2); } #endif if (res == FR_OK) { /* Object to be renamed is found */ @@ -5184,8 +5254,8 @@ FRESULT f_chmod ( ) { FRESULT res; - DIR dj; FATFS *fs; + DIR dj; DEF_NAMBUF @@ -5230,8 +5300,8 @@ FRESULT f_utime ( ) { FRESULT res; - DIR dj; FATFS *fs; + DIR dj; DEF_NAMBUF @@ -5278,8 +5348,8 @@ FRESULT f_getlabel ( ) { FRESULT res; - DIR dj; FATFS *fs; + DIR dj; UINT si, di; WCHAR wc; @@ -5304,7 +5374,9 @@ FRESULT f_getlabel ( hs = wc; continue; } nw = put_utf((DWORD)hs << 16 | wc, &label[di], 4); /* Store it in API encoding */ - if (nw == 0) { di = 0; break; } /* Encode error? */ + if (nw == 0) { /* Encode error? */ + di = 0; break; + } di += nw; hs = 0; } @@ -5319,7 +5391,9 @@ FRESULT f_getlabel ( #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) { di = 0; break; } /* Invalid char in current code page? */ + if (wc == 0) { /* Invalid char in current code page? */ + di = 0; break; + } di += put_utf(wc, &label[di], 4); /* Store it in Unicode */ #else /* ANSI/OEM output */ label[di++] = (TCHAR)wc; @@ -5373,8 +5447,8 @@ FRESULT f_setlabel ( ) { FRESULT res; - DIR dj; FATFS *fs; + DIR dj; BYTE dirvn[22]; UINT di; WCHAR wc; @@ -5530,14 +5604,20 @@ FRESULT f_expand ( for (;;) { /* Find a contiguous cluster block */ n = get_fat(&fp->obj, clst); if (++clst >= fs->n_fatent) clst = 2; - if (n == 1) { res = FR_INT_ERR; break; } - if (n == 0xFFFFFFFF) { res = FR_DISK_ERR; break; } + if (n == 1) { + res = FR_INT_ERR; break; + } + if (n == 0xFFFFFFFF) { + res = FR_DISK_ERR; break; + } if (n == 0) { /* Is it a free cluster? */ if (++ncl == tcl) break; /* Break if a contiguous cluster block is found */ } else { scl = clst; ncl = 0; /* Not a free cluster */ } - if (clst == stcl) { res = FR_DENIED; break; } /* No contiguous cluster? */ + if (clst == stcl) { /* No contiguous cluster? */ + res = FR_DENIED; break; + } } if (res == FR_OK) { /* A contiguous free area is found */ if (opt) { /* Allocate it now */ @@ -5659,8 +5739,8 @@ FRESULT f_forward ( static FRESULT create_partition ( BYTE drv, /* Physical drive number */ const LBA_t plst[], /* Partition list */ - BYTE sys, /* System ID (for only MBR, temp setting) */ - BYTE* buf /* Working buffer for a sector */ + BYTE sys, /* System ID for each partition (for only MBR) */ + BYTE *buf /* Working buffer for a sector */ ) { UINT i, cy; @@ -5689,7 +5769,7 @@ static FRESULT create_partition ( 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 */ + top_bpt = sz_drv - sz_ptbl - 1; /* Backup partition 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; @@ -5802,14 +5882,16 @@ static FRESULT create_partition ( FRESULT f_mkfs ( const TCHAR* path, /* Logical drive number */ const MKFS_PARM* opt, /* Format options */ - void* work, /* Pointer to working buffer (null: use heap memory) */ + void* work, /* Pointer to working buffer (null: use len bytes of heap memory) */ UINT len /* Size of working buffer [byte] */ ) { static const WORD cst[] = {1, 4, 16, 64, 256, 512, 0}; /* Cluster size boundary for FAT volume (4Ks unit) */ static const WORD cst32[] = {1, 2, 4, 8, 16, 32, 0}; /* Cluster size boundary for FAT32 volume (128Ks unit) */ static const MKFS_PARM defopt = {FM_ANY, 0, 0, 0, 0}; /* Default parameter */ - BYTE fsopt, fsty, sys, *buf, *pte, pdrv, ipart; + BYTE fsopt, fsty, sys, pdrv, ipart; + BYTE *buf; + BYTE *pte; WORD ss; /* Sector size */ 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 */ @@ -5818,30 +5900,33 @@ FRESULT f_mkfs ( UINT n_fat, n_root, i; /* Index, Number of FATs and Number of roor dir entries */ int vol; DSTATUS ds; - FRESULT fr; + FRESULT res; /* Check mounted drive and clear work area */ vol = get_ldnumber(&path); /* Get target logical drive */ if (vol < 0) return FR_INVALID_DRIVE; if (FatFs[vol]) FatFs[vol]->fs_type = 0; /* Clear the fs object if mounted */ - pdrv = LD2PD(vol); /* Physical drive */ - ipart = LD2PT(vol); /* Partition (0:create as new, 1..:get from partition table) */ - if (!opt) opt = &defopt; /* Use default parameter if it is not given */ + pdrv = LD2PD(vol); /* Hosting physical drive */ + ipart = LD2PT(vol); /* Hosting partition (0:create as new, 1..:existing partition) */ - /* Get physical drive status (sz_drv, sz_blk, ss) */ + /* Initialize the hosting physical drive */ ds = disk_initialize(pdrv); if (ds & STA_NOINIT) return FR_NOT_READY; if (ds & STA_PROTECT) return FR_WRITE_PROTECTED; + + /* Get physical drive parameters (sz_drv, sz_blk and ss) */ + if (!opt) opt = &defopt; /* Use default parameter if it is not given */ sz_blk = opt->align; - if (sz_blk == 0 && disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_blk) != RES_OK) sz_blk = 1; - if (sz_blk == 0 || sz_blk > 0x8000 || (sz_blk & (sz_blk - 1))) sz_blk = 1; + if (sz_blk == 0) disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_blk); /* Block size from the paramter or lower layer */ + if (sz_blk == 0 || sz_blk > 0x8000 || (sz_blk & (sz_blk - 1))) sz_blk = 1; /* Use default if the block size is invalid */ #if FF_MAX_SS != FF_MIN_SS if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &ss) != RES_OK) return FR_DISK_ERR; if (ss > FF_MAX_SS || ss < FF_MIN_SS || (ss & (ss - 1))) return FR_DISK_ERR; #else ss = FF_MAX_SS; #endif + /* Options for FAT sub-type and FAT parameters */ fsopt = opt->fmt & (FM_ANY | FM_SFD); n_fat = (opt->n_fat >= 1 && opt->n_fat <= 2) ? opt->n_fat : 1; @@ -5957,7 +6042,7 @@ FRESULT f_mkfs ( sz_fat = (DWORD)((sz_vol / sz_au + 2) * 4 + ss - 1) / ss; /* Number of FAT sectors */ b_data = (b_fat + sz_fat + sz_blk - 1) & ~((LBA_t)sz_blk - 1); /* Align data area to the erase block boundary */ if (b_data - b_vol >= sz_vol / 2) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume? */ - n_clst = (DWORD)(sz_vol - (b_data - b_vol)) / sz_au; /* Number of clusters */ + n_clst = (DWORD)((sz_vol - (b_data - b_vol)) / sz_au); /* Number of clusters */ 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? */ @@ -6258,32 +6343,30 @@ FRESULT f_mkfs ( /* Determine system ID in the MBR partition table */ if (FF_FS_EXFAT && fsty == FS_EXFAT) { - sys = 0x07; /* exFAT */ + sys = 0x07; /* exFAT */ + } else if (fsty == FS_FAT32) { + sys = 0x0C; /* FAT32X */ + } else if (sz_vol >= 0x10000) { + sys = 0x06; /* FAT12/16 (large) */ + } else if (fsty == FS_FAT16) { + sys = 0x04; /* FAT16 */ } else { - if (fsty == FS_FAT32) { - sys = 0x0C; /* FAT32X */ - } else { - if (sz_vol >= 0x10000) { - sys = 0x06; /* FAT12/16 (large) */ - } else { - sys = (fsty == FS_FAT16) ? 0x04 : 0x01; /* FAT16 : FAT12 */ - } - } + sys = 0x01; /* FAT12 */ } /* Update partition information */ if (FF_MULTI_PARTITION && ipart != 0) { /* Volume is in the existing partition */ - if (!FF_LBA64 || !(fsopt & 0x80)) { + if (!FF_LBA64 || !(fsopt & 0x80)) { /* Is the partition in MBR? */ /* Update system ID in the partition table */ if (disk_read(pdrv, buf, 0, 1) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); /* Read the MBR */ buf[MBR_Table + (ipart - 1) * SZ_PTE + PTE_System] = sys; /* Set system ID */ 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 */ + if (!(fsopt & FM_SFD)) { /* Create partition table if not in SFD format */ lba[0] = sz_vol; lba[1] = 0; - fr = create_partition(pdrv, lba, sys, buf); - if (fr != FR_OK) LEAVE_MKFS(fr); + res = create_partition(pdrv, lba, sys, buf); + if (res != FR_OK) LEAVE_MKFS(res); } } @@ -6308,17 +6391,22 @@ FRESULT f_fdisk ( { BYTE *buf = (BYTE*)work; DSTATUS stat; + FRESULT res; + /* Initialize the physical drive */ stat = disk_initialize(pdrv); if (stat & STA_NOINIT) return FR_NOT_READY; if (stat & STA_PROTECT) return FR_WRITE_PROTECTED; + #if FF_USE_LFN == 3 if (!buf) buf = ff_memalloc(FF_MAX_SS); /* Use heap memory for working buffer */ #endif if (!buf) return FR_NOT_ENOUGH_CORE; - LEAVE_MKFS(create_partition(pdrv, ptbl, 0x07, buf)); + res = create_partition(pdrv, ptbl, 0x07, buf); /* Create partitions (system ID is temporary setting and determined by f_mkfs) */ + + LEAVE_MKFS(res); } #endif /* FF_MULTI_PARTITION */ @@ -6388,9 +6476,15 @@ TCHAR* f_gets ( dc = s[0]; if (dc >= 0x80) { /* Multi-byte sequence? */ ct = 0; - if ((dc & 0xE0) == 0xC0) { dc &= 0x1F; ct = 1; } /* 2-byte sequence? */ - if ((dc & 0xF0) == 0xE0) { dc &= 0x0F; ct = 2; } /* 3-byte sequence? */ - if ((dc & 0xF8) == 0xF0) { dc &= 0x07; ct = 3; } /* 4-byte sequence? */ + if ((dc & 0xE0) == 0xC0) { /* 2-byte sequence? */ + dc &= 0x1F; ct = 1; + } + if ((dc & 0xF0) == 0xE0) { /* 3-byte sequence? */ + dc &= 0x0F; ct = 2; + } + if ((dc & 0xF8) == 0xF0) { /* 4-byte sequence? */ + dc &= 0x07; ct = 3; + } if (ct == 0) continue; f_read(fp, s, ct, &rc); /* Get trailing bytes */ if (rc != ct) break; @@ -6417,25 +6511,21 @@ TCHAR* f_gets ( *p++ = (TCHAR)dc; nc++; if (dc == '\n') break; /* End of line? */ - } else { - if (dc < 0x800) { /* 2-byte sequence? */ - *p++ = (TCHAR)(0xC0 | (dc >> 6 & 0x1F)); - *p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F)); - nc += 2; - } else { - if (dc < 0x10000) { /* 3-byte sequence? */ - *p++ = (TCHAR)(0xE0 | (dc >> 12 & 0x0F)); - *p++ = (TCHAR)(0x80 | (dc >> 6 & 0x3F)); - *p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F)); - nc += 3; - } else { /* 4-byte sequence? */ - *p++ = (TCHAR)(0xF0 | (dc >> 18 & 0x07)); - *p++ = (TCHAR)(0x80 | (dc >> 12 & 0x3F)); - *p++ = (TCHAR)(0x80 | (dc >> 6 & 0x3F)); - *p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F)); - nc += 4; - } - } + } else if (dc < 0x800) { /* 2-byte sequence? */ + *p++ = (TCHAR)(0xC0 | (dc >> 6 & 0x1F)); + *p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F)); + nc += 2; + } else if (dc < 0x10000) { /* 3-byte sequence? */ + *p++ = (TCHAR)(0xE0 | (dc >> 12 & 0x0F)); + *p++ = (TCHAR)(0x80 | (dc >> 6 & 0x3F)); + *p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F)); + nc += 3; + } else { /* 4-byte sequence */ + *p++ = (TCHAR)(0xF0 | (dc >> 18 & 0x07)); + *p++ = (TCHAR)(0x80 | (dc >> 12 & 0x3F)); + *p++ = (TCHAR)(0x80 | (dc >> 6 & 0x3F)); + *p++ = (TCHAR)(0x80 | (dc >> 0 & 0x3F)); + nc += 4; } #endif } @@ -6493,7 +6583,7 @@ static void putc_bfd (putbuff* pb, TCHAR c) WCHAR hs, wc; #if FF_LFN_UNICODE == 2 DWORD dc; - const TCHAR *tp; + const TCHAR* tp; #endif #endif @@ -6507,39 +6597,39 @@ static void putc_bfd (putbuff* pb, TCHAR c) #if FF_USE_LFN && FF_LFN_UNICODE #if FF_LFN_UNICODE == 1 /* UTF-16 input */ - if (IsSurrogateH(c)) { /* High surrogate? */ + if (IsSurrogateH(c)) { /* Is this a high-surrogate? */ pb->hs = c; return; /* Save it for next */ } hs = pb->hs; pb->hs = 0; - if (hs != 0) { /* There is a leading high surrogate */ - if (!IsSurrogateL(c)) hs = 0; /* Discard high surrogate if not a surrogate pair */ + if (hs != 0) { /* Is there a leading high-surrogate? */ + if (!IsSurrogateL(c)) hs = 0; /* Discard high-surrogate if not a surrogate pair */ } else { - if (IsSurrogateL(c)) return; /* Discard stray low surrogate */ + if (IsSurrogateL(c)) return; /* Discard stray low-surrogate */ } wc = c; #elif FF_LFN_UNICODE == 2 /* UTF-8 input */ for (;;) { if (pb->ct == 0) { /* Out of multi-byte sequence? */ pb->bs[pb->wi = 0] = (BYTE)c; /* Save 1st byte */ - if ((BYTE)c < 0x80) break; /* Single byte? */ + if ((BYTE)c < 0x80) break; /* Single byte code? */ if (((BYTE)c & 0xE0) == 0xC0) pb->ct = 1; /* 2-byte sequence? */ if (((BYTE)c & 0xF0) == 0xE0) pb->ct = 2; /* 3-byte sequence? */ - if (((BYTE)c & 0xF1) == 0xF0) pb->ct = 3; /* 4-byte sequence? */ - return; + if (((BYTE)c & 0xF8) == 0xF0) pb->ct = 3; /* 4-byte sequence? */ + return; /* Wrong leading byte (discard it) */ } else { /* In the multi-byte sequence */ if (((BYTE)c & 0xC0) != 0x80) { /* Broken sequence? */ - pb->ct = 0; continue; + pb->ct = 0; continue; /* Discard the sequense */ } pb->bs[++pb->wi] = (BYTE)c; /* Save the trailing byte */ - if (--pb->ct == 0) break; /* End of multi-byte sequence? */ + if (--pb->ct == 0) break; /* End of the sequence? */ return; } } tp = (const TCHAR*)pb->bs; - dc = tchar2uni(&tp); /* UTF-8 ==> UTF-16 */ + dc = tchar2uni(&tp); /* UTF-8 ==> UTF-16 */ if (dc == 0xFFFFFFFF) return; /* Wrong code? */ - wc = (WCHAR)dc; hs = (WCHAR)(dc >> 16); + wc = (WCHAR)dc; #elif FF_LFN_UNICODE == 3 /* UTF-32 input */ if (IsSurrogate(c) || c >= 0x110000) return; /* Discard invalid code */ if (c >= 0x10000) { /* Out of BMP? */ @@ -6742,7 +6832,7 @@ static void ftoa ( er = "NaN"; } else { if (prec < 0) prec = 6; /* Default precision? (6 fractional digits) */ - if (val < 0) { /* Nagative? */ + if (val < 0) { /* Negative? */ val = 0 - val; sign = '-'; } else { sign = '+'; @@ -6790,7 +6880,9 @@ static void ftoa ( } if (er) { /* Error condition */ if (sign) *buf++ = sign; /* Add sign if needed */ - do *buf++ = *er++; while (*er); /* Put error symbol */ + do { /* Put error symbol */ + *buf++ = *er++; + } while (*er); } *buf = 0; /* Term */ } @@ -6813,7 +6905,8 @@ int f_printf ( #else DWORD v; #endif - TCHAR tc, pad, *tp; + TCHAR *tp; + TCHAR tc, pad; TCHAR nul = 0; char d, str[SZ_NUM_BUF]; @@ -6870,17 +6963,22 @@ int f_printf ( switch (tc) { /* Atgument type is... */ case 'b': /* Unsigned binary */ r = 2; break; + case 'o': /* Unsigned octal */ r = 8; break; + case 'd': /* Signed decimal */ - case 'u': /* Unsigned decimal */ + case 'u': /* Unsigned decimal */ r = 10; break; - case 'x': /* Unsigned hexdecimal (lower case) */ - case 'X': /* Unsigned hexdecimal (upper case) */ + + case 'x': /* Unsigned hexadecimal (lower case) */ + case 'X': /* Unsigned hexadecimal (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 */ @@ -6894,7 +6992,7 @@ int f_printf ( 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 */ + ftoa(str, va_arg(arp, double), prec, tc); /* Make a floating 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 */ @@ -6906,14 +7004,12 @@ int f_printf ( /* 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 (f & 8) { /* long long argument? */ + v = (QWORD)va_arg(arp, long long); + } else if (f & 4) { /* long argument? */ + v = (tc == 'd') ? (QWORD)(long long)va_arg(arp, long) : (QWORD)va_arg(arp, unsigned long); + } else { /* int/short/char argument */ + v = (tc == 'd') ? (QWORD)(long long)va_arg(arp, int) : (QWORD)va_arg(arp, unsigned int); } if (tc == 'd' && (v & 0x8000000000000000)) { /* Negative value? */ v = 0 - v; f |= 1; @@ -6936,9 +7032,15 @@ int f_printf ( } 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 */ + for (j = i; !(f & 2) && j < w; j++) { /* Left pads */ + putc_bfd(&pb, pad); + } + do { /* Body */ + putc_bfd(&pb, (TCHAR)str[--i]); + } while (i); + while (j++ < w) { /* Right pads */ + putc_bfd(&pb, ' '); + } } va_end(arp); @@ -6961,12 +7063,12 @@ FRESULT f_setcp ( ) { 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}; + 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; for (i = 0; validcp[i] != 0 && validcp[i] != cp; i++) ; /* Find the code page */ - if (validcp[i] != cp) return FR_INVALID_PARAMETER; /* Not found? */ + if (validcp[i] != cp) return FR_INVALID_PARAMETER; /* Not found? */ CodePage = cp; if (cp >= 900) { /* DBCS */ diff --git a/drivers/fatfs/ff.h b/drivers/fatfs/ff.h index 48665763..e0a77124 100644 --- a/drivers/fatfs/ff.h +++ b/drivers/fatfs/ff.h @@ -1,8 +1,8 @@ /*----------------------------------------------------------------------------/ -/ FatFs - Generic FAT Filesystem module R0.14b / +/ FatFs - Generic FAT Filesystem module R0.15 / /-----------------------------------------------------------------------------/ / -/ Copyright (C) 2021, ChaN, all right reserved. +/ Copyright (C) 2022, 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,7 +20,7 @@ #ifndef FF_DEFINED -#define FF_DEFINED 86631 /* Revision ID */ +#define FF_DEFINED 80286 /* Revision ID */ #ifdef __cplusplus extern "C" { @@ -131,10 +131,11 @@ extern const char* VolumeStr[FF_VOLUMES]; /* User defied volume ID */ typedef struct { BYTE fs_type; /* Filesystem type (0:not mounted) */ - BYTE pdrv; /* Associated physical drive */ + BYTE pdrv; /* Volume hosting physical drive */ + BYTE ldrv; /* Logical drive number (used only when FF_FS_REENTRANT) */ BYTE n_fats; /* Number of FATs (1 or 2) */ - BYTE wflag; /* win[] flag (b0:dirty) */ - BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */ + BYTE wflag; /* win[] status (b0:dirty) */ + BYTE fsi_flag; /* FSINFO status (b7:disabled, b0:dirty) */ WORD id; /* Volume mount ID */ WORD n_rootdir; /* Number of root directory entries (FAT12/16) */ WORD csize; /* Cluster size [sectors] */ @@ -147,9 +148,6 @@ typedef struct { #if FF_FS_EXFAT BYTE* dirbuf; /* Directory entry block scratchpad buffer for exFAT */ #endif -#if FF_FS_REENTRANT - FF_SYNC_t sobj; /* Identifier of sync object */ -#endif #if !FF_FS_READONLY DWORD last_clst; /* Last allocated cluster */ DWORD free_clst; /* Number of free clusters */ @@ -163,10 +161,10 @@ typedef struct { #endif #endif DWORD n_fatent; /* Number of FAT entries (number of clusters + 2) */ - DWORD fsize; /* Size of an FAT [sectors] */ + DWORD fsize; /* Number of sectors per FAT */ LBA_t volbase; /* Volume base sector */ LBA_t fatbase; /* FAT base sector */ - LBA_t dirbase; /* Root directory base sector/cluster */ + LBA_t dirbase; /* Root directory base sector (FAT12/16) or cluster (FAT32/exFAT) */ LBA_t database; /* Data base sector */ #if FF_FS_EXFAT LBA_t bitbase; /* Allocation bitmap base sector */ @@ -181,7 +179,7 @@ typedef struct { typedef struct { FATFS* fs; /* Pointer to the hosting volume of this object */ - WORD id; /* Hosting volume mount ID */ + WORD id; /* Hosting volume's mount ID */ BYTE attr; /* Object attribute */ BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:fragmented in this session, b2:sub-directory stretched) */ DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */ @@ -250,7 +248,7 @@ typedef struct { WORD ftime; /* Modified time */ BYTE fattrib; /* File attribute */ #if FF_USE_LFN - TCHAR altname[FF_SFN_BUF + 1];/* Altenative file name */ + TCHAR altname[FF_SFN_BUF + 1];/* Alternative file name */ TCHAR fname[FF_LFN_BUF + 1]; /* Primary file name */ #else TCHAR fname[12 + 1]; /* File name */ @@ -298,8 +296,10 @@ typedef enum { + +/*--------------------------------------------------------------*/ +/* FatFs Module Application Interface */ /*--------------------------------------------------------------*/ -/* FatFs module application interface */ FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */ FRESULT f_close (FIL* fp); /* Close an open file object */ @@ -336,6 +336,8 @@ int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */ int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */ TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */ +/* Some API fucntions are implemented as macro */ + #define f_eof(fp) ((int)((fp)->fptr == (fp)->obj.objsize)) #define f_error(fp) ((fp)->err) #define f_tell(fp) ((fp)->fptr) @@ -349,38 +351,43 @@ TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the fil /*--------------------------------------------------------------*/ -/* Additional user defined functions */ +/* Additional Functions */ +/*--------------------------------------------------------------*/ -/* RTC function */ +/* RTC function (provided by user) */ #if !FF_FS_READONLY && !FF_FS_NORTC -DWORD get_fattime (void); +DWORD get_fattime (void); /* Get current time */ #endif -/* LFN support functions */ -#if FF_USE_LFN >= 1 /* Code conversion (defined in unicode.c) */ + +/* LFN support functions (defined in ffunicode.c) */ + +#if FF_USE_LFN >= 1 WCHAR ff_oem2uni (WCHAR oem, WORD cp); /* OEM code to Unicode conversion */ WCHAR ff_uni2oem (DWORD uni, WORD cp); /* Unicode to OEM code conversion */ DWORD ff_wtoupper (DWORD uni); /* Unicode upper-case conversion */ #endif -#if FF_USE_LFN == 3 /* Dynamic memory allocation */ -void* ff_memalloc (UINT msize); /* Allocate memory block */ -void ff_memfree (void* mblock); /* Free memory block */ -#endif -/* Sync functions */ -#if FF_FS_REENTRANT -int ff_cre_syncobj (BYTE vol, FF_SYNC_t* sobj); /* Create a sync object */ -int ff_req_grant (FF_SYNC_t sobj); /* Lock sync object */ -void ff_rel_grant (FF_SYNC_t sobj); /* Unlock sync object */ -int ff_del_syncobj (FF_SYNC_t sobj); /* Delete a sync object */ + +/* O/S dependent functions (samples available in ffsystem.c) */ + +#if FF_USE_LFN == 3 /* Dynamic memory allocation */ +void* ff_memalloc (UINT msize); /* Allocate memory block */ +void ff_memfree (void* mblock); /* Free memory block */ +#endif +#if FF_FS_REENTRANT /* Sync functions */ +int ff_mutex_create (int vol); /* Create a sync object */ +void ff_mutex_delete (int vol); /* Delete a sync object */ +int ff_mutex_take (int vol); /* Lock sync object */ +void ff_mutex_give (int vol); /* Unlock sync object */ #endif /*--------------------------------------------------------------*/ -/* Flags and offset address */ - +/* Flags and Offset Address */ +/*--------------------------------------------------------------*/ /* File access mode and open method flags (3rd argument of f_open) */ #define FA_READ 0x01 diff --git a/drivers/fatfs/ffconf.h b/drivers/fatfs/ffconf.h index f12c18c0..af63a515 100644 --- a/drivers/fatfs/ffconf.h +++ b/drivers/fatfs/ffconf.h @@ -1,8 +1,8 @@ /*---------------------------------------------------------------------------/ -/ FatFs Functional Configurations +/ Configurations of FatFs Module /---------------------------------------------------------------------------*/ -#define FFCONF_DEF 86631 /* Revision ID */ +#define FFCONF_DEF 80286 /* Revision ID */ /*---------------------------------------------------------------------------/ / Function Configurations @@ -68,7 +68,7 @@ / 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. +/ 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. @@ -178,7 +178,7 @@ / logical drives. Number of items must not be less than FF_VOLUMES. Valid / characters for the volume ID strings are A-Z, a-z and 0-9, however, they are / compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is -/ not defined, a user defined volume string table needs to be defined as: +/ not defined, a user defined volume string table is needed as: / / const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",... */ @@ -190,7 +190,7 @@ / number and only an FAT volume found on the physical drive will be mounted. / When this function is enabled (1), each logical drive number can be bound to / arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk() -/ funciton will be available. */ +/ function will be available. */ #define FF_MIN_SS 512 @@ -237,13 +237,13 @@ / Note that enabling exFAT discards ANSI C (C89) compatibility. */ -#define FF_FS_NORTC 1 -#define FF_NORTC_MON 1 -#define FF_NORTC_MDAY 1 -#define FF_NORTC_YEAR 2020 -/* The option FF_FS_NORTC switches timestamp function. 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 +#define FF_FS_NORTC 0 +#define FF_NORTC_MON 5 +#define FF_NORTC_MDAY 12 +#define FF_NORTC_YEAR 2023 +/* The option FF_FS_NORTC switches timestamp feature. If the system does not have +/ an RTC or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable the +/ timestamp feature. Every object modified by FatFs will have a fixed timestamp / defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time. / To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be / added to the project to read current time form real-time clock. FF_NORTC_MON, @@ -253,7 +253,7 @@ #define FF_FS_NOFSINFO 0 /* If you need to know correct free space on the FAT32 volume, set bit 0 of this -/ option, and f_getfree() function at first time after volume mount will force +/ option, and f_getfree() function at the first time after volume mount will force / a full FAT scan. Bit 1 controls the use of last allocated cluster number. / / bit0=0: Use free cluster count in the FSINFO if available. @@ -275,26 +275,21 @@ / lock control is independent of re-entrancy. */ -/* #include // O/S definitions */ #define FF_FS_REENTRANT 0 #define FF_FS_TIMEOUT 1000 -#define FF_SYNC_t HANDLE /* The option FF_FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs / module itself. Note that regardless of this option, file access to different / volume is always re-entrant and volume control functions, f_mount(), f_mkfs() / and f_fdisk() function, are always not re-entrant. Only file/directory access -/ to the same volume is under control of this function. +/ to the same volume is under control of this featuer. / -/ 0: Disable re-entrancy. FF_FS_TIMEOUT and FF_SYNC_t have no effect. +/ 0: Disable re-entrancy. FF_FS_TIMEOUT have no effect. / 1: Enable re-entrancy. Also user provided synchronization handlers, -/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj() -/ function, must be added to the project. Samples are available in -/ option/syscall.c. +/ ff_mutex_create(), ff_mutex_delete(), ff_mutex_take() and ff_mutex_give() +/ function, must be added to the project. Samples are available in ffsystem.c. / -/ The FF_FS_TIMEOUT defines timeout period in unit of time tick. -/ The FF_SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*, -/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be -/ included somewhere in the scope of ff.h. */ +/ The FF_FS_TIMEOUT defines timeout period in unit of O/S time tick. +*/ diff --git a/drivers/fatfs/ffsystem.c b/drivers/fatfs/ffsystem.c index b88ce155..d5c5134b 100644 --- a/drivers/fatfs/ffsystem.c +++ b/drivers/fatfs/ffsystem.c @@ -1,170 +1,208 @@ /*------------------------------------------------------------------------*/ -/* Sample Code of OS Dependent Functions for FatFs */ -/* (C)ChaN, 2018 */ +/* A Sample Code of User Provided OS Dependent Functions for FatFs */ /*------------------------------------------------------------------------*/ - #include "ff.h" -#if FF_USE_LFN == 3 /* Dynamic memory allocation */ +#if FF_USE_LFN == 3 /* Use dynamic memory allocation */ /*------------------------------------------------------------------------*/ -/* Allocate a memory block */ +/* Allocate/Free a Memory Block */ /*------------------------------------------------------------------------*/ +#include /* with POSIX API */ + + void* ff_memalloc ( /* Returns pointer to the allocated memory block (null if not enough core) */ UINT msize /* Number of bytes to allocate */ ) { - return malloc(msize); /* Allocate a new memory block with POSIX API */ + return malloc((size_t)msize); /* Allocate a new memory block */ } -/*------------------------------------------------------------------------*/ -/* Free a memory block */ -/*------------------------------------------------------------------------*/ - void ff_memfree ( - void* mblock /* Pointer to the memory block to free (nothing to do if null) */ + void* mblock /* Pointer to the memory block to free (no effect if null) */ ) { - free(mblock); /* Free the memory block with POSIX API */ + free(mblock); /* Free the memory block */ } #endif + #if FF_FS_REENTRANT /* Mutal exclusion */ - /*------------------------------------------------------------------------*/ -/* Create a Synchronization Object */ +/* Definitions of Mutex */ /*------------------------------------------------------------------------*/ -/* This function is called in f_mount() function to create a new -/ synchronization object for the volume, such as semaphore and mutex. -/ When a 0 is returned, the f_mount() function fails with FR_INT_ERR. -*/ -//const osMutexDef_t Mutex[FF_VOLUMES]; /* Table of CMSIS-RTOS mutex */ +#define OS_TYPE 0 /* 0:Win32, 1:uITRON4.0, 2:uC/OS-II, 3:FreeRTOS, 4:CMSIS-RTOS */ -int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object */ - BYTE vol, /* Corresponding volume (logical drive number) */ - FF_SYNC_t* sobj /* Pointer to return the created sync object */ -) -{ - /* Win32 */ - *sobj = CreateMutex(NULL, FALSE, NULL); - return (int)(*sobj != INVALID_HANDLE_VALUE); +#if OS_TYPE == 0 /* Win32 */ +#include +static HANDLE Mutex[FF_VOLUMES + 1]; /* Table of mutex handle */ - /* uITRON */ -// T_CSEM csem = {TA_TPRI,1,1}; -// *sobj = acre_sem(&csem); -// return (int)(*sobj > 0); +#elif OS_TYPE == 1 /* uITRON */ +#include "itron.h" +#include "kernel.h" +static mtxid Mutex[FF_VOLUMES + 1]; /* Table of mutex ID */ - /* uC/OS-II */ -// OS_ERR err; -// *sobj = OSMutexCreate(0, &err); -// return (int)(err == OS_NO_ERR); +#elif OS_TYPE == 2 /* uc/OS-II */ +#include "includes.h" +static OS_EVENT *Mutex[FF_VOLUMES + 1]; /* Table of mutex pinter */ - /* FreeRTOS */ -// *sobj = xSemaphoreCreateMutex(); -// return (int)(*sobj != NULL); +#elif OS_TYPE == 3 /* FreeRTOS */ +#include "FreeRTOS.h" +#include "semphr.h" +static SemaphoreHandle_t Mutex[FF_VOLUMES + 1]; /* Table of mutex handle */ - /* CMSIS-RTOS */ -// *sobj = osMutexCreate(&Mutex[vol]); -// return (int)(*sobj != NULL); -} - - -/*------------------------------------------------------------------------*/ -/* Delete a Synchronization Object */ -/*------------------------------------------------------------------------*/ -/* This function is called in f_mount() function to delete a synchronization -/ object that created with ff_cre_syncobj() function. When a 0 is returned, -/ the f_mount() function fails with FR_INT_ERR. -*/ - -int ff_del_syncobj ( /* 1:Function succeeded, 0:Could not delete due to an error */ - FF_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */ -) -{ - /* Win32 */ - return (int)CloseHandle(sobj); - - /* uITRON */ -// return (int)(del_sem(sobj) == E_OK); - - /* uC/OS-II */ -// OS_ERR err; -// OSMutexDel(sobj, OS_DEL_ALWAYS, &err); -// return (int)(err == OS_NO_ERR); - - /* FreeRTOS */ -// vSemaphoreDelete(sobj); -// return 1; - - /* CMSIS-RTOS */ -// return (int)(osMutexDelete(sobj) == osOK); -} - - -/*------------------------------------------------------------------------*/ -/* Request Grant to Access the Volume */ -/*------------------------------------------------------------------------*/ -/* This function is called on entering file functions to lock the volume. -/ When a 0 is returned, the file function fails with FR_TIMEOUT. -*/ - -int ff_req_grant ( /* 1:Got a grant to access the volume, 0:Could not get a grant */ - FF_SYNC_t sobj /* Sync object to wait */ -) -{ - /* Win32 */ - return (int)(WaitForSingleObject(sobj, FF_FS_TIMEOUT) == WAIT_OBJECT_0); - - /* uITRON */ -// return (int)(wai_sem(sobj) == E_OK); - - /* uC/OS-II */ -// OS_ERR err; -// OSMutexPend(sobj, FF_FS_TIMEOUT, &err)); -// return (int)(err == OS_NO_ERR); - - /* FreeRTOS */ -// return (int)(xSemaphoreTake(sobj, FF_FS_TIMEOUT) == pdTRUE); - - /* CMSIS-RTOS */ -// return (int)(osMutexWait(sobj, FF_FS_TIMEOUT) == osOK); -} - - -/*------------------------------------------------------------------------*/ -/* Release Grant to Access the Volume */ -/*------------------------------------------------------------------------*/ -/* This function is called on leaving file functions to unlock the volume. -*/ - -void ff_rel_grant ( - FF_SYNC_t sobj /* Sync object to be signaled */ -) -{ - /* Win32 */ - ReleaseMutex(sobj); - - /* uITRON */ -// sig_sem(sobj); - - /* uC/OS-II */ -// OSMutexPost(sobj); - - /* FreeRTOS */ -// xSemaphoreGive(sobj); - - /* CMSIS-RTOS */ -// osMutexRelease(sobj); -} +#elif OS_TYPE == 4 /* CMSIS-RTOS */ +#include "cmsis_os.h" +static osMutexId Mutex[FF_VOLUMES + 1]; /* Table of mutex ID */ #endif + + +/*------------------------------------------------------------------------*/ +/* Create a Mutex */ +/*------------------------------------------------------------------------*/ +/* This function is called in f_mount function to create a new mutex +/ or semaphore for the volume. When a 0 is returned, the f_mount function +/ fails with FR_INT_ERR. +*/ + +int ff_mutex_create ( /* Returns 1:Function succeeded or 0:Could not create the mutex */ + int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */ +) +{ +#if OS_TYPE == 0 /* Win32 */ + Mutex[vol] = CreateMutex(NULL, FALSE, NULL); + return (int)(Mutex[vol] != INVALID_HANDLE_VALUE); + +#elif OS_TYPE == 1 /* uITRON */ + T_CMTX cmtx = {TA_TPRI,1}; + + Mutex[vol] = acre_mtx(&cmtx); + return (int)(Mutex[vol] > 0); + +#elif OS_TYPE == 2 /* uC/OS-II */ + OS_ERR err; + + Mutex[vol] = OSMutexCreate(0, &err); + return (int)(err == OS_NO_ERR); + +#elif OS_TYPE == 3 /* FreeRTOS */ + Mutex[vol] = xSemaphoreCreateMutex(); + return (int)(Mutex[vol] != NULL); + +#elif OS_TYPE == 4 /* CMSIS-RTOS */ + osMutexDef(cmsis_os_mutex); + + Mutex[vol] = osMutexCreate(osMutex(cmsis_os_mutex)); + return (int)(Mutex[vol] != NULL); + +#endif +} + + +/*------------------------------------------------------------------------*/ +/* Delete a Mutex */ +/*------------------------------------------------------------------------*/ +/* This function is called in f_mount function to delete a mutex or +/ semaphore of the volume created with ff_mutex_create function. +*/ + +void ff_mutex_delete ( /* Returns 1:Function succeeded or 0:Could not delete due to an error */ + int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */ +) +{ +#if OS_TYPE == 0 /* Win32 */ + CloseHandle(Mutex[vol]); + +#elif OS_TYPE == 1 /* uITRON */ + del_mtx(Mutex[vol]); + +#elif OS_TYPE == 2 /* uC/OS-II */ + OS_ERR err; + + OSMutexDel(Mutex[vol], OS_DEL_ALWAYS, &err); + +#elif OS_TYPE == 3 /* FreeRTOS */ + vSemaphoreDelete(Mutex[vol]); + +#elif OS_TYPE == 4 /* CMSIS-RTOS */ + osMutexDelete(Mutex[vol]); + +#endif +} + + +/*------------------------------------------------------------------------*/ +/* Request a Grant to Access the Volume */ +/*------------------------------------------------------------------------*/ +/* This function is called on enter file functions to lock the volume. +/ When a 0 is returned, the file function fails with FR_TIMEOUT. +*/ + +int ff_mutex_take ( /* Returns 1:Succeeded or 0:Timeout */ + int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */ +) +{ +#if OS_TYPE == 0 /* Win32 */ + return (int)(WaitForSingleObject(Mutex[vol], FF_FS_TIMEOUT) == WAIT_OBJECT_0); + +#elif OS_TYPE == 1 /* uITRON */ + return (int)(tloc_mtx(Mutex[vol], FF_FS_TIMEOUT) == E_OK); + +#elif OS_TYPE == 2 /* uC/OS-II */ + OS_ERR err; + + OSMutexPend(Mutex[vol], FF_FS_TIMEOUT, &err)); + return (int)(err == OS_NO_ERR); + +#elif OS_TYPE == 3 /* FreeRTOS */ + return (int)(xSemaphoreTake(Mutex[vol], FF_FS_TIMEOUT) == pdTRUE); + +#elif OS_TYPE == 4 /* CMSIS-RTOS */ + return (int)(osMutexWait(Mutex[vol], FF_FS_TIMEOUT) == osOK); + +#endif +} + + + +/*------------------------------------------------------------------------*/ +/* Release a Grant to Access the Volume */ +/*------------------------------------------------------------------------*/ +/* This function is called on leave file functions to unlock the volume. +*/ + +void ff_mutex_give ( + int vol /* Mutex ID: Volume mutex (0 to FF_VOLUMES - 1) or system mutex (FF_VOLUMES) */ +) +{ +#if OS_TYPE == 0 /* Win32 */ + ReleaseMutex(Mutex[vol]); + +#elif OS_TYPE == 1 /* uITRON */ + unl_mtx(Mutex[vol]); + +#elif OS_TYPE == 2 /* uC/OS-II */ + OSMutexPost(Mutex[vol]); + +#elif OS_TYPE == 3 /* FreeRTOS */ + xSemaphoreGive(Mutex[vol]); + +#elif OS_TYPE == 4 /* CMSIS-RTOS */ + osMutexRelease(Mutex[vol]); + +#endif +} + +#endif /* FF_FS_REENTRANT */ + diff --git a/drivers/fatfs/ffunicode.c b/drivers/fatfs/ffunicode.c index a69b24c8..e6bcacae 100644 --- a/drivers/fatfs/ffunicode.c +++ b/drivers/fatfs/ffunicode.c @@ -1,13 +1,13 @@ /*------------------------------------------------------------------------*/ -/* Unicode handling functions for FatFs R0.13+ */ +/* Unicode Handling Functions for FatFs R0.13 and Later */ +/*------------------------------------------------------------------------*/ +/* This module will occupy a huge memory in the .rodata section when the */ +/* FatFs is configured for LFN with DBCS. If the system has a Unicode */ +/* library for the code conversion, this module should be modified to use */ +/* it to avoid silly memory consumption. */ /*------------------------------------------------------------------------*/ -/* This module will occupy a huge memory in the .const section when the / -/ FatFs is configured for LFN with DBCS. If the system has any Unicode / -/ utilitiy for the code conversion, this module should be modified to use / -/ that function to avoid silly memory consumption. / -/-------------------------------------------------------------------------*/ /* -/ Copyright (C) 2014, ChaN, all right reserved. +/ Copyright (C) 2022, 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 @@ -25,7 +25,7 @@ #include "ff.h" -#if FF_USE_LFN /* This module will be blanked if non-LFN configuration */ +#if FF_USE_LFN != 0 /* This module will be blanked if in non-LFN configuration */ #define MERGE2(a, b) a ## b #define CVTBL(tbl, cp) MERGE2(tbl, cp) @@ -15214,8 +15214,8 @@ static const WCHAR uc869[] = { /* CP869(Greek 2) to Unicode conversion table */ /*------------------------------------------------------------------------*/ -/* OEM <==> Unicode conversions for static code page configuration */ -/* SBCS fixed code page */ +/* OEM <==> Unicode Conversions for Static Code Page Configuration with */ +/* SBCS Fixed Code Page */ /*------------------------------------------------------------------------*/ #if FF_CODE_PAGE != 0 && FF_CODE_PAGE < 900 @@ -15225,7 +15225,7 @@ WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */ ) { WCHAR c = 0; - const WCHAR *p = CVTBL(uc, FF_CODE_PAGE); + const WCHAR* p = CVTBL(uc, FF_CODE_PAGE); if (uni < 0x80) { /* ASCII? */ @@ -15247,7 +15247,7 @@ WCHAR ff_oem2uni ( /* Returns Unicode character in UTF-16, zero on error */ ) { WCHAR c = 0; - const WCHAR *p = CVTBL(uc, FF_CODE_PAGE); + const WCHAR* p = CVTBL(uc, FF_CODE_PAGE); if (oem < 0x80) { /* ASCII? */ @@ -15267,8 +15267,8 @@ WCHAR ff_oem2uni ( /* Returns Unicode character in UTF-16, zero on error */ /*------------------------------------------------------------------------*/ -/* OEM <==> Unicode conversions for static code page configuration */ -/* DBCS fixed code page */ +/* OEM <==> Unicode Conversions for Static Code Page Configuration with */ +/* DBCS Fixed Code Page */ /*------------------------------------------------------------------------*/ #if FF_CODE_PAGE >= 900 @@ -15277,7 +15277,7 @@ WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */ WORD cp /* Code page for the conversion */ ) { - const WCHAR *p; + const WCHAR* p; WCHAR c = 0, uc; UINT i = 0, n, li, hi; @@ -15313,7 +15313,7 @@ WCHAR ff_oem2uni ( /* Returns Unicode character in UTF-16, zero on error */ WORD cp /* Code page for the conversion */ ) { - const WCHAR *p; + const WCHAR* p; WCHAR c = 0; UINT i = 0, n, li, hi; @@ -15346,7 +15346,7 @@ WCHAR ff_oem2uni ( /* Returns Unicode character in UTF-16, zero on error */ /*------------------------------------------------------------------------*/ -/* OEM <==> Unicode conversions for dynamic code page configuration */ +/* OEM <==> Unicode Conversions for Dynamic Code Page Configuration */ /*------------------------------------------------------------------------*/ #if FF_CODE_PAGE == 0 @@ -15360,7 +15360,7 @@ WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */ WORD cp /* Code page for the conversion */ ) { - const WCHAR *p; + const WCHAR* p; WCHAR c = 0, uc; UINT i, n, li, hi; @@ -15412,7 +15412,7 @@ WCHAR ff_oem2uni ( /* Returns Unicode character in UTF-16, zero on error */ WORD cp /* Code page for the conversion */ ) { - const WCHAR *p; + const WCHAR* p; WCHAR c = 0; UINT i, n, li, hi; @@ -15458,14 +15458,14 @@ WCHAR ff_oem2uni ( /* Returns Unicode character in UTF-16, zero on error */ /*------------------------------------------------------------------------*/ -/* Unicode up-case conversion */ +/* Unicode Up-case Conversion */ /*------------------------------------------------------------------------*/ DWORD ff_wtoupper ( /* Returns up-converted code point */ DWORD uni /* Unicode code point to be up-converted */ ) { - const WORD *p; + const WORD* p; WORD uc, bc, nc, cmd; static const WORD cvt1[] = { /* Compressed up conversion table for U+0000 - U+0FFF */ /* Basic Latin */ @@ -15590,4 +15590,4 @@ DWORD ff_wtoupper ( /* Returns up-converted code point */ } -#endif /* #if FF_USE_LFN */ +#endif /* #if FF_USE_LFN != 0 */