mirror of
https://github.com/CTCaer/hekate
synced 2024-12-22 11:21:23 +00:00
[FatFS] Update to R0.13c (p3)
This commit is contained in:
parent
ff9671c481
commit
491c4efe9c
7 changed files with 207 additions and 192 deletions
|
@ -15,6 +15,9 @@
|
||||||
|
|
||||||
extern sdmmc_storage_t sd_storage;
|
extern sdmmc_storage_t sd_storage;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* Get Drive Status */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
DSTATUS disk_status (
|
DSTATUS disk_status (
|
||||||
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||||
)
|
)
|
||||||
|
@ -22,6 +25,9 @@ DSTATUS disk_status (
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* Inidialize a Drive */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
DSTATUS disk_initialize (
|
DSTATUS disk_initialize (
|
||||||
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||||
)
|
)
|
||||||
|
@ -29,6 +35,9 @@ DSTATUS disk_initialize (
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* Read Sector(s) */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
DRESULT disk_read (
|
DRESULT disk_read (
|
||||||
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
||||||
BYTE *buff, /* Data buffer to store read data */
|
BYTE *buff, /* Data buffer to store read data */
|
||||||
|
@ -38,7 +47,7 @@ DRESULT disk_read (
|
||||||
{
|
{
|
||||||
if ((u32)buff >= 0x90000000)
|
if ((u32)buff >= 0x90000000)
|
||||||
return sdmmc_storage_read(&sd_storage, sector, count, buff) ? RES_OK : RES_ERROR;
|
return sdmmc_storage_read(&sd_storage, sector, count, buff) ? RES_OK : RES_ERROR;
|
||||||
u8 *buf = (u8 *)SDMMC_UPPER_BUFFER; //TODO: define this somewhere.
|
u8 *buf = (u8 *)SDMMC_UPPER_BUFFER;
|
||||||
if (sdmmc_storage_read(&sd_storage, sector, count, buf))
|
if (sdmmc_storage_read(&sd_storage, sector, count, buf))
|
||||||
{
|
{
|
||||||
memcpy(buff, buf, 512 * count);
|
memcpy(buff, buf, 512 * count);
|
||||||
|
@ -47,6 +56,9 @@ DRESULT disk_read (
|
||||||
return RES_ERROR;
|
return RES_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* Write Sector(s) */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
DRESULT disk_write (
|
DRESULT disk_write (
|
||||||
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
||||||
const BYTE *buff, /* Data to be written */
|
const BYTE *buff, /* Data to be written */
|
||||||
|
@ -63,6 +75,9 @@ DRESULT disk_write (
|
||||||
return RES_ERROR;
|
return RES_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* Miscellaneous Functions */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
DRESULT disk_ioctl (
|
DRESULT disk_ioctl (
|
||||||
BYTE pdrv, /* Physical drive nmuber (0..) */
|
BYTE pdrv, /* Physical drive nmuber (0..) */
|
||||||
BYTE cmd, /* Control code */
|
BYTE cmd, /* Control code */
|
||||||
|
|
|
@ -11,7 +11,6 @@ extern "C" {
|
||||||
|
|
||||||
#include "../../utils/types.h"
|
#include "../../utils/types.h"
|
||||||
|
|
||||||
|
|
||||||
/* Status of Disk Functions */
|
/* Status of Disk Functions */
|
||||||
typedef BYTE DSTATUS;
|
typedef BYTE DSTATUS;
|
||||||
|
|
||||||
|
@ -46,11 +45,11 @@ DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
|
||||||
/* Command code for disk_ioctrl fucntion */
|
/* Command code for disk_ioctrl fucntion */
|
||||||
|
|
||||||
/* Generic command (Used by FatFs) */
|
/* Generic command (Used by FatFs) */
|
||||||
#define CTRL_SYNC 0 /* Complete pending write process (needed at _FS_READONLY == 0) */
|
#define CTRL_SYNC 0 /* Complete pending write process (needed at FF_FS_READONLY == 0) */
|
||||||
#define GET_SECTOR_COUNT 1 /* Get media size (needed at _USE_MKFS == 1) */
|
#define GET_SECTOR_COUNT 1 /* Get media size (needed at FF_USE_MKFS == 1) */
|
||||||
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at _MAX_SS != _MIN_SS) */
|
#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 _USE_MKFS == 1) */
|
#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 _USE_TRIM == 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) */
|
/* Generic command (Not used by FatFs) */
|
||||||
#define CTRL_POWER 5 /* Get/Set power status */
|
#define CTRL_POWER 5 /* Get/Set power status */
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
/*----------------------------------------------------------------------------/
|
/*----------------------------------------------------------------------------/
|
||||||
/ FatFs - Generic FAT Filesystem Module R0.13b /
|
/ FatFs - Generic FAT Filesystem Module R0.13c (p3) /
|
||||||
/-----------------------------------------------------------------------------/
|
/-----------------------------------------------------------------------------/
|
||||||
/
|
/
|
||||||
/ Copyright (C) 2018, ChaN, all right reserved.
|
/ Copyright (C) 2018, ChaN, all right reserved.
|
||||||
/ Copyright (c) 2018 naehrwert
|
/ Copyright (c) 2018 naehrwert
|
||||||
/ Copyright (C) 2018 CTCaer
|
/ Copyright (C) 2018-2019 CTCaer
|
||||||
/
|
/
|
||||||
/ FatFs module is an open source software. Redistribution and use of FatFs in
|
/ FatFs module is an open source software. Redistribution and use of FatFs in
|
||||||
/ source and binary forms, with or without modification, are permitted provided
|
/ source and binary forms, with or without modification, are permitted provided
|
||||||
|
@ -34,11 +34,20 @@
|
||||||
|
|
||||||
---------------------------------------------------------------------------*/
|
---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#if FF_DEFINED != 63463 /* Revision ID */
|
#if FF_DEFINED != 86604 /* Revision ID */
|
||||||
#error Wrong include file (ff.h).
|
#error Wrong include file (ff.h).
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Limits and boundaries */
|
||||||
|
#define MAX_DIR 0x200000 /* Max size of FAT directory */
|
||||||
|
#define MAX_DIR_EX 0x10000000 /* Max size of exFAT directory */
|
||||||
|
#define MAX_FAT12 0xFF5 /* Max FAT12 clusters (differs from specs, but right for real DOS/Windows behavior) */
|
||||||
|
#define MAX_FAT16 0xFFF5 /* Max FAT16 clusters (differs from specs, but right for real DOS/Windows behavior) */
|
||||||
|
#define MAX_FAT32 0x0FFFFFF5 /* Max FAT32 clusters (not specified, practical limit) */
|
||||||
|
#define MAX_EXFAT 0x7FFFFFFD /* Max exFAT clusters (differs from specs, implementation limit) */
|
||||||
|
|
||||||
|
|
||||||
/* Character code support macros */
|
/* Character code support macros */
|
||||||
#define IsUpper(c) ((c) >= 'A' && (c) <= 'Z')
|
#define IsUpper(c) ((c) >= 'A' && (c) <= 'Z')
|
||||||
#define IsLower(c) ((c) >= 'a' && (c) <= 'z')
|
#define IsLower(c) ((c) >= 'a' && (c) <= 'z')
|
||||||
|
@ -48,18 +57,18 @@
|
||||||
#define IsSurrogateL(c) ((c) >= 0xDC00 && (c) <= 0xDFFF)
|
#define IsSurrogateL(c) ((c) >= 0xDC00 && (c) <= 0xDFFF)
|
||||||
|
|
||||||
|
|
||||||
/* 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 */
|
|
||||||
|
|
||||||
|
|
||||||
/* Additional file access control and file status flags for internal use */
|
/* Additional file access control and file status flags for internal use */
|
||||||
#define FA_SEEKEND 0x20 /* Seek to end of the file on file open */
|
#define FA_SEEKEND 0x20 /* Seek to end of the file on file open */
|
||||||
#define FA_MODIFIED 0x40 /* File has been modified */
|
#define FA_MODIFIED 0x40 /* File has been modified */
|
||||||
#define FA_DIRTY 0x80 /* FIL.buf[] needs to be written-back */
|
#define FA_DIRTY 0x80 /* FIL.buf[] needs to be written-back */
|
||||||
|
|
||||||
|
|
||||||
|
/* 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 */
|
||||||
|
|
||||||
|
|
||||||
/* Name status flags in fn[11] */
|
/* Name status flags in fn[11] */
|
||||||
#define NSFLAG 11 /* Index of the name status byte */
|
#define NSFLAG 11 /* Index of the name status byte */
|
||||||
#define NS_LOSS 0x01 /* Out of 8.3 format */
|
#define NS_LOSS 0x01 /* Out of 8.3 format */
|
||||||
|
@ -72,13 +81,13 @@
|
||||||
#define NS_NONAME 0x80 /* Not followed */
|
#define NS_NONAME 0x80 /* Not followed */
|
||||||
|
|
||||||
|
|
||||||
/* Limits and boundaries */
|
/* exFAT directory entry types */
|
||||||
#define MAX_DIR 0x200000 /* Max size of FAT directory */
|
#define ET_BITMAP 0x81 /* Allocation bitmap */
|
||||||
#define MAX_DIR_EX 0x10000000 /* Max size of exFAT directory */
|
#define ET_UPCASE 0x82 /* Up-case table */
|
||||||
#define MAX_FAT12 0xFF5 /* Max FAT12 clusters (differs from specs, but right for real DOS/Windows behavior) */
|
#define ET_VLABEL 0x83 /* Volume label */
|
||||||
#define MAX_FAT16 0xFFF5 /* Max FAT16 clusters (differs from specs, but right for real DOS/Windows behavior) */
|
#define ET_FILEDIR 0x85 /* File and directory */
|
||||||
#define MAX_FAT32 0x0FFFFFF5 /* Max FAT32 clusters (not specified, practical limit) */
|
#define ET_STREAM 0xC0 /* Stream extension */
|
||||||
#define MAX_EXFAT 0x7FFFFFFD /* Max exFAT clusters (differs from specs, implementation limit) */
|
#define ET_FILENAME 0xC1 /* Name extension */
|
||||||
|
|
||||||
|
|
||||||
/* FatFs refers the FAT structure as simple byte array instead of structure member
|
/* FatFs refers the FAT structure as simple byte array instead of structure member
|
||||||
|
@ -526,6 +535,7 @@ static WCHAR LfnBuf[FF_MAX_LFN + 1]; /* LFN working buffer */
|
||||||
#define CODEPAGE CodePage
|
#define CODEPAGE CodePage
|
||||||
static WORD CodePage; /* Current code page */
|
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, *DbcTbl; /* Pointer to current SBCS up-case table and DBCS code range table below */
|
||||||
|
|
||||||
static const BYTE Ct437[] = TBL_CT437;
|
static const BYTE Ct437[] = TBL_CT437;
|
||||||
static const BYTE Ct720[] = TBL_CT720;
|
static const BYTE Ct720[] = TBL_CT720;
|
||||||
static const BYTE Ct737[] = TBL_CT737;
|
static const BYTE Ct737[] = TBL_CT737;
|
||||||
|
@ -1107,7 +1117,7 @@ static FRESULT sync_fs ( /* Returns FR_OK or FR_DISK_ERR */
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) { /* FAT32: Update FSInfo sector if needed */
|
if (fs->fs_type == FS_FAT32 && fs->fsi_flag == 1) { /* FAT32: Update FSInfo sector if needed */
|
||||||
/* Create FSInfo structure */
|
/* Create FSInfo structure */
|
||||||
mem_set(fs->win, 0, SS(fs));
|
mem_set(fs->win, 0, sizeof fs->win);
|
||||||
st_word(fs->win + BS_55AA, 0xAA55);
|
st_word(fs->win + BS_55AA, 0xAA55);
|
||||||
st_dword(fs->win + FSI_LeadSig, 0x41615252);
|
st_dword(fs->win + FSI_LeadSig, 0x41615252);
|
||||||
st_dword(fs->win + FSI_StrucSig, 0x61417272);
|
st_dword(fs->win + FSI_StrucSig, 0x61417272);
|
||||||
|
@ -1307,7 +1317,7 @@ static DWORD find_bitmap ( /* 0:Not found, 2..:Cluster block found, 0xFFFFFFFF:D
|
||||||
if (clst >= fs->n_fatent - 2) clst = 0;
|
if (clst >= fs->n_fatent - 2) clst = 0;
|
||||||
scl = val = clst; ctr = 0;
|
scl = val = clst; ctr = 0;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (move_window(fs, fs->database + val / 8 / SS(fs)) != FR_OK) return 0xFFFFFFFF; /* (assuming bitmap is located top of the cluster heap) */
|
if (move_window(fs, fs->bitbase + val / 8 / SS(fs)) != FR_OK) return 0xFFFFFFFF;
|
||||||
i = val / 8 % SS(fs); bm = 1 << (val % 8);
|
i = val / 8 % SS(fs); bm = 1 << (val % 8);
|
||||||
do {
|
do {
|
||||||
do {
|
do {
|
||||||
|
@ -1345,9 +1355,9 @@ static FRESULT change_bitmap (
|
||||||
|
|
||||||
|
|
||||||
clst -= 2; /* The first bit corresponds to cluster #2 */
|
clst -= 2; /* The first bit corresponds to cluster #2 */
|
||||||
sect = fs->database + clst / 8 / SS(fs); /* Sector address (assuming bitmap is located top of the cluster heap) */
|
sect = fs->bitbase + clst / 8 / SS(fs); /* Sector address */
|
||||||
i = clst / 8 % SS(fs); /* Byte offset in the sector */
|
i = clst / 8 % SS(fs); /* Byte offset in the sector */
|
||||||
bm = 1 << (clst % 8); /* Bit mask in the byte */
|
bm = 1 << (clst % 8); /* Bit mask in the byte */
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (move_window(fs, sect++) != FR_OK) return FR_DISK_ERR;
|
if (move_window(fs, sect++) != FR_OK) return FR_DISK_ERR;
|
||||||
do {
|
do {
|
||||||
|
@ -1420,7 +1430,7 @@ static FRESULT fill_last_frag (
|
||||||
static FRESULT remove_chain ( /* FR_OK(0):succeeded, !=0:error */
|
static FRESULT remove_chain ( /* FR_OK(0):succeeded, !=0:error */
|
||||||
FFOBJID* obj, /* Corresponding object */
|
FFOBJID* obj, /* Corresponding object */
|
||||||
DWORD clst, /* Cluster to remove a chain from */
|
DWORD clst, /* Cluster to remove a chain from */
|
||||||
DWORD pclst /* Previous cluster of clst (0:entire chain) */
|
DWORD pclst /* Previous cluster of clst (0 if entire chain) */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
FRESULT res = FR_OK;
|
FRESULT res = FR_OK;
|
||||||
|
@ -1658,7 +1668,7 @@ 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 */
|
if (sync_window(fs) != FR_OK) return FR_DISK_ERR; /* Flush disk access window */
|
||||||
sect = clst2sect(fs, clst); /* Top of the cluster */
|
sect = clst2sect(fs, clst); /* Top of the cluster */
|
||||||
fs->winsect = sect; /* Set window to top of the cluster */
|
fs->winsect = sect; /* Set window to top of the cluster */
|
||||||
mem_set(fs->win, 0, SS(fs)); /* Clear window buffer */
|
mem_set(fs->win, 0, sizeof fs->win); /* Clear window buffer */
|
||||||
#if FF_USE_LFN == 3 /* Quick table clear by using multi-secter write */
|
#if FF_USE_LFN == 3 /* Quick table clear by using multi-secter write */
|
||||||
/* Allocate a temporary buffer */
|
/* 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) ;
|
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) ;
|
||||||
|
@ -1888,7 +1898,7 @@ static int cmp_lfn ( /* 1:matched, 0:not matched */
|
||||||
for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */
|
for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */
|
||||||
uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */
|
uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */
|
||||||
if (wc != 0) {
|
if (wc != 0) {
|
||||||
if (i >= FF_MAX_LFN || ff_wtoupper(uc) != ff_wtoupper(lfnbuf[i++])) { /* Compare it */
|
if (i >= FF_MAX_LFN + 1 || ff_wtoupper(uc) != ff_wtoupper(lfnbuf[i++])) { /* Compare it */
|
||||||
return 0; /* Not matched */
|
return 0; /* Not matched */
|
||||||
}
|
}
|
||||||
wc = uc;
|
wc = uc;
|
||||||
|
@ -1924,15 +1934,15 @@ static int pick_lfn ( /* 1:succeeded, 0:buffer overflow or invalid LFN entry */
|
||||||
for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */
|
for (wc = 1, s = 0; s < 13; s++) { /* Process all characters in the entry */
|
||||||
uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */
|
uc = ld_word(dir + LfnOfs[s]); /* Pick an LFN character */
|
||||||
if (wc != 0) {
|
if (wc != 0) {
|
||||||
if (i >= FF_MAX_LFN) return 0; /* Buffer overflow? */
|
if (i >= FF_MAX_LFN + 1) return 0; /* Buffer overflow? */
|
||||||
lfnbuf[i++] = wc = uc; /* Store it */
|
lfnbuf[i++] = wc = uc; /* Store it */
|
||||||
} else {
|
} else {
|
||||||
if (uc != 0xFFFF) return 0; /* Check filler */
|
if (uc != 0xFFFF) return 0; /* Check filler */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dir[LDIR_Ord] & LLEF) { /* Put terminator if it is the last LFN part */
|
if (dir[LDIR_Ord] & LLEF && wc != 0) { /* Put terminator if it is the last LFN part and not terminated */
|
||||||
if (i >= FF_MAX_LFN) return 0; /* Buffer overflow? */
|
if (i >= FF_MAX_LFN + 1) return 0; /* Buffer overflow? */
|
||||||
lfnbuf[i] = 0;
|
lfnbuf[i] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2168,33 +2178,33 @@ static FRESULT load_xdir ( /* FR_INT_ERR: invalid entry block */
|
||||||
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 85 entry */
|
/* Load file-directory entry */
|
||||||
res = move_window(dp->obj.fs, dp->sect);
|
res = move_window(dp->obj.fs, dp->sect);
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
if (dp->dir[XDIR_Type] != 0x85) return FR_INT_ERR; /* Invalid order */
|
if (dp->dir[XDIR_Type] != ET_FILEDIR) return FR_INT_ERR; /* Invalid order */
|
||||||
mem_cpy(dirb + 0 * SZDIRE, dp->dir, SZDIRE);
|
mem_cpy(dirb + 0 * SZDIRE, dp->dir, SZDIRE);
|
||||||
sz_ent = (dirb[XDIR_NumSec] + 1) * SZDIRE;
|
sz_ent = (dirb[XDIR_NumSec] + 1) * SZDIRE;
|
||||||
if (sz_ent < 3 * SZDIRE || sz_ent > 19 * SZDIRE) return FR_INT_ERR;
|
if (sz_ent < 3 * SZDIRE || sz_ent > 19 * SZDIRE) return FR_INT_ERR;
|
||||||
|
|
||||||
/* Load C0 entry */
|
/* Load stream-extension entry */
|
||||||
res = dir_next(dp, 0);
|
res = dir_next(dp, 0);
|
||||||
if (res == FR_NO_FILE) res = FR_INT_ERR; /* It cannot be */
|
if (res == FR_NO_FILE) res = FR_INT_ERR; /* It cannot be */
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
res = move_window(dp->obj.fs, dp->sect);
|
res = move_window(dp->obj.fs, dp->sect);
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
if (dp->dir[XDIR_Type] != 0xC0) return FR_INT_ERR; /* Invalid order */
|
if (dp->dir[XDIR_Type] != ET_STREAM) return FR_INT_ERR; /* Invalid order */
|
||||||
mem_cpy(dirb + 1 * SZDIRE, dp->dir, SZDIRE);
|
mem_cpy(dirb + 1 * SZDIRE, dp->dir, SZDIRE);
|
||||||
if (MAXDIRB(dirb[XDIR_NumName]) > sz_ent) return FR_INT_ERR;
|
if (MAXDIRB(dirb[XDIR_NumName]) > sz_ent) return FR_INT_ERR;
|
||||||
|
|
||||||
/* Load C1 entries */
|
/* Load file-name entries */
|
||||||
i = 2 * SZDIRE; /* C1 offset to load */
|
i = 2 * SZDIRE; /* Name offset to load */
|
||||||
do {
|
do {
|
||||||
res = dir_next(dp, 0);
|
res = dir_next(dp, 0);
|
||||||
if (res == FR_NO_FILE) res = FR_INT_ERR; /* It cannot be */
|
if (res == FR_NO_FILE) res = FR_INT_ERR; /* It cannot be */
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
res = move_window(dp->obj.fs, dp->sect);
|
res = move_window(dp->obj.fs, dp->sect);
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
if (dp->dir[XDIR_Type] != 0xC1) return FR_INT_ERR; /* Invalid order */
|
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)) mem_cpy(dirb + i, dp->dir, SZDIRE);
|
||||||
} while ((i += SZDIRE) < sz_ent);
|
} while ((i += SZDIRE) < sz_ent);
|
||||||
|
|
||||||
|
@ -2299,16 +2309,16 @@ static void create_xdir (
|
||||||
WCHAR wc;
|
WCHAR wc;
|
||||||
|
|
||||||
|
|
||||||
/* Create 85,C0 entry */
|
/* Create file-directory and stream-extension entry */
|
||||||
mem_set(dirb, 0, 2 * SZDIRE);
|
mem_set(dirb, 0, 2 * SZDIRE);
|
||||||
dirb[0 * SZDIRE + XDIR_Type] = 0x85; /* 85 entry */
|
dirb[0 * SZDIRE + XDIR_Type] = ET_FILEDIR;
|
||||||
dirb[1 * SZDIRE + XDIR_Type] = 0xC0; /* C0 entry */
|
dirb[1 * SZDIRE + XDIR_Type] = ET_STREAM;
|
||||||
|
|
||||||
/* Create C1 entries */
|
/* Create file-name entries */
|
||||||
i = SZDIRE * 2; /* Top of C1 entries */
|
i = SZDIRE * 2; /* Top of file_name entries */
|
||||||
nlen = nc1 = 0; wc = 1;
|
nlen = nc1 = 0; wc = 1;
|
||||||
do {
|
do {
|
||||||
dirb[i++] = 0xC1; dirb[i++] = 0; /* Entry type C1 */
|
dirb[i++] = ET_FILENAME; dirb[i++] = 0;
|
||||||
do { /* Fill name field */
|
do { /* Fill name field */
|
||||||
if (wc != 0 && (wc = lfn[nlen]) != 0) nlen++; /* Get a character if exist */
|
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 */
|
||||||
|
@ -2332,8 +2342,8 @@ static void create_xdir (
|
||||||
/* Read an object from the directory */
|
/* Read an object from the directory */
|
||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
#define dir_read_file(dp) dir_read(dp, 0)
|
#define DIR_READ_FILE(dp) dir_read(dp, 0)
|
||||||
#define dir_read_label(dp) dir_read(dp, 1)
|
#define DIR_READ_LABEL(dp) dir_read(dp, 1)
|
||||||
|
|
||||||
static FRESULT dir_read (
|
static FRESULT dir_read (
|
||||||
DIR* dp, /* Pointer to the directory object */
|
DIR* dp, /* Pointer to the directory object */
|
||||||
|
@ -2342,7 +2352,7 @@ static FRESULT dir_read (
|
||||||
{
|
{
|
||||||
FRESULT res = FR_NO_FILE;
|
FRESULT res = FR_NO_FILE;
|
||||||
FATFS *fs = dp->obj.fs;
|
FATFS *fs = dp->obj.fs;
|
||||||
BYTE a, c;
|
BYTE attr, b;
|
||||||
#if FF_USE_LFN
|
#if FF_USE_LFN
|
||||||
BYTE ord = 0xFF, sum = 0xFF;
|
BYTE ord = 0xFF, sum = 0xFF;
|
||||||
#endif
|
#endif
|
||||||
|
@ -2350,16 +2360,16 @@ static FRESULT dir_read (
|
||||||
while (dp->sect) {
|
while (dp->sect) {
|
||||||
res = move_window(fs, dp->sect);
|
res = move_window(fs, dp->sect);
|
||||||
if (res != FR_OK) break;
|
if (res != FR_OK) break;
|
||||||
c = dp->dir[DIR_Name]; /* Test for the entry type */
|
b = dp->dir[DIR_Name]; /* Test for the entry type */
|
||||||
if (c == 0) {
|
if (b == 0) {
|
||||||
res = FR_NO_FILE; break; /* Reached to end of the directory */
|
res = FR_NO_FILE; break; /* Reached to end of the directory */
|
||||||
}
|
}
|
||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
|
if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
|
||||||
if (FF_USE_LABEL && vol) {
|
if (FF_USE_LABEL && vol) {
|
||||||
if (c == 0x83) break; /* Volume label entry? */
|
if (b == ET_VLABEL) break; /* Volume label entry? */
|
||||||
} else {
|
} else {
|
||||||
if (c == 0x85) { /* Start of the file entry block? */
|
if (b == ET_FILEDIR) { /* Start of the file entry block? */
|
||||||
dp->blk_ofs = dp->dptr; /* Get location of the block */
|
dp->blk_ofs = dp->dptr; /* Get location of the block */
|
||||||
res = load_xdir(dp); /* Load the entry block */
|
res = load_xdir(dp); /* Load the entry block */
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
|
@ -2371,19 +2381,19 @@ static FRESULT dir_read (
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{ /* On the FAT/FAT32 volume */
|
{ /* On the FAT/FAT32 volume */
|
||||||
dp->obj.attr = a = dp->dir[DIR_Attr] & AM_MASK; /* Get attribute */
|
dp->obj.attr = attr = dp->dir[DIR_Attr] & AM_MASK; /* Get attribute */
|
||||||
#if FF_USE_LFN /* LFN configuration */
|
#if FF_USE_LFN /* LFN configuration */
|
||||||
if (c == DDEM || c == '.' || (int)((a & ~AM_ARC) == AM_VOL) != vol) { /* An entry without valid data */
|
if (b == DDEM || b == '.' || (int)((attr & ~AM_ARC) == AM_VOL) != vol) { /* An entry without valid data */
|
||||||
ord = 0xFF;
|
ord = 0xFF;
|
||||||
} else {
|
} else {
|
||||||
if (a == AM_LFN) { /* An LFN entry is found */
|
if (attr == AM_LFN) { /* An LFN entry is found */
|
||||||
if (c & LLEF) { /* Is it start of an LFN sequence? */
|
if (b & LLEF) { /* Is it start of an LFN sequence? */
|
||||||
sum = dp->dir[LDIR_Chksum];
|
sum = dp->dir[LDIR_Chksum];
|
||||||
c &= (BYTE)~LLEF; ord = c;
|
b &= (BYTE)~LLEF; ord = b;
|
||||||
dp->blk_ofs = dp->dptr;
|
dp->blk_ofs = dp->dptr;
|
||||||
}
|
}
|
||||||
/* Check LFN validity and capture it */
|
/* Check LFN validity and capture it */
|
||||||
ord = (c == ord && sum == dp->dir[LDIR_Chksum] && pick_lfn(fs->lfnbuf, dp->dir)) ? ord - 1 : 0xFF;
|
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? */
|
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. */
|
||||||
|
@ -2392,7 +2402,7 @@ static FRESULT dir_read (
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#else /* Non LFN configuration */
|
#else /* Non LFN configuration */
|
||||||
if (c != DDEM && c != '.' && a != AM_LFN && (int)((a & ~AM_ARC) == AM_VOL) == vol) { /* Is it a valid entry? */
|
if (b != DDEM && b != '.' && attr != AM_LFN && (int)((attr & ~AM_ARC) == AM_VOL) == vol) { /* Is it a valid entry? */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -2432,7 +2442,7 @@ static FRESULT dir_find ( /* FR_OK(0):succeeded, !=0:error */
|
||||||
UINT di, ni;
|
UINT di, ni;
|
||||||
WORD hash = xname_sum(fs->lfnbuf); /* Hash value of the name to find */
|
WORD hash = xname_sum(fs->lfnbuf); /* Hash value of the name to find */
|
||||||
|
|
||||||
while ((res = dir_read_file(dp)) == FR_OK) { /* Read an item */
|
while ((res = DIR_READ_FILE(dp)) == FR_OK) { /* Read an item */
|
||||||
#if FF_MAX_LFN < 255
|
#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
|
#endif
|
||||||
|
@ -2511,17 +2521,17 @@ static FRESULT dir_register ( /* FR_OK:succeeded, FR_DENIED:no free entry or too
|
||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
|
if (fs->fs_type == FS_EXFAT) { /* On the exFAT volume */
|
||||||
nent = (nlen + 14) / 15 + 2; /* Number of entries to allocate (85+C0+C1s) */
|
nent = (nlen + 14) / 15 + 2; /* Number of entries to allocate (85+C0+C1s) */
|
||||||
res = dir_alloc(dp, nent); /* Allocate entries */
|
res = dir_alloc(dp, nent); /* Allocate directory entries */
|
||||||
if (res != FR_OK) return res;
|
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 * (nent - 1); /* Set the allocated entry block offset */
|
||||||
|
|
||||||
if (dp->obj.stat & 4) { /* Has the directory been stretched? */
|
if (dp->obj.stat & 4) { /* Has the directory been stretched by new allocation? */
|
||||||
dp->obj.stat &= ~4;
|
dp->obj.stat &= ~4;
|
||||||
res = fill_first_frag(&dp->obj); /* Fill the first fragment on the FAT if needed */
|
res = fill_first_frag(&dp->obj); /* Fill the first fragment on the FAT if needed */
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
res = fill_last_frag(&dp->obj, dp->clust, 0xFFFFFFFF); /* Fill the last fragment on the FAT if needed */
|
res = fill_last_frag(&dp->obj, dp->clust, 0xFFFFFFFF); /* Fill the last fragment on the FAT if needed */
|
||||||
if (res != FR_OK) return res;
|
if (res != FR_OK) return res;
|
||||||
if (dp->obj.sclust != 0) { /* Is it a sub directory? */
|
if (dp->obj.sclust != 0) { /* Is it a sub-directory? */
|
||||||
DIR dj;
|
DIR dj;
|
||||||
|
|
||||||
res = load_obj_xdir(&dj, &dp->obj); /* Load the object status */
|
res = load_obj_xdir(&dj, &dp->obj); /* Load the object status */
|
||||||
|
@ -2653,6 +2663,7 @@ static void get_fileinfo (
|
||||||
{
|
{
|
||||||
UINT si, di;
|
UINT si, di;
|
||||||
#if FF_USE_LFN
|
#if FF_USE_LFN
|
||||||
|
BYTE lcf;
|
||||||
WCHAR wc, hs;
|
WCHAR wc, hs;
|
||||||
FATFS *fs = dp->obj.fs;
|
FATFS *fs = dp->obj.fs;
|
||||||
#else
|
#else
|
||||||
|
@ -2713,9 +2724,10 @@ static void get_fileinfo (
|
||||||
if (di == 0) { /* If LFN and SFN both are invalid, this object is inaccesible */
|
if (di == 0) { /* If LFN and SFN both are invalid, this object is inaccesible */
|
||||||
fno->fname[di++] = '?';
|
fno->fname[di++] = '?';
|
||||||
} else {
|
} else {
|
||||||
for (si = di = 0; fno->altname[si]; si++, di++) { /* Copy altname[] to fname[] with case information */
|
for (si = di = 0, lcf = NS_BODY; fno->altname[si]; si++, di++) { /* Copy altname[] to fname[] with case information */
|
||||||
wc = (WCHAR)fno->altname[si];
|
wc = (WCHAR)fno->altname[si];
|
||||||
if (IsUpper(wc) && (dp->dir[DIR_NTres] & ((si >= 9) ? NS_EXT : NS_BODY))) wc += 0x20;
|
if (wc == '.') lcf = NS_EXT;
|
||||||
|
if (IsUpper(wc) && (dp->dir[DIR_NTres] & lcf)) wc += 0x20;
|
||||||
fno->fname[di] = (TCHAR)wc;
|
fno->fname[di] = (TCHAR)wc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3272,7 +3284,7 @@ static FRESULT find_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;
|
if (SS(fs) > FF_MAX_SS || SS(fs) < FF_MIN_SS || (SS(fs) & (SS(fs) - 1))) return FR_DISK_ERR;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Find an FAT partition on the drive. Supports only generic partitioning rules, FDISK and SFD. */
|
/* Find an FAT partition on the drive. Supports only generic partitioning rules, FDISK (MBR) and SFD (w/o partition). */
|
||||||
bsect = 0;
|
bsect = 0;
|
||||||
fmt = check_fs(fs, bsect); /* Load sector 0 and check if it is an FAT-VBR as SFD */
|
fmt = check_fs(fs, bsect); /* Load sector 0 and check if it is an FAT-VBR as SFD */
|
||||||
if (fmt == 2 || (fmt < 2 && LD2PT(vol) != 0)) { /* Not an FAT-VBR or forced partition number */
|
if (fmt == 2 || (fmt < 2 && LD2PT(vol) != 0)) { /* Not an FAT-VBR or forced partition number */
|
||||||
|
@ -3301,13 +3313,12 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
if (fmt == 1) {
|
if (fmt == 1) {
|
||||||
QWORD maxlba;
|
QWORD maxlba;
|
||||||
|
DWORD so, cv, bcl;
|
||||||
|
|
||||||
for (i = BPB_ZeroedEx; i < BPB_ZeroedEx + 53 && fs->win[i] == 0; i++) ; /* Check zero filler */
|
for (i = BPB_ZeroedEx; i < BPB_ZeroedEx + 53 && fs->win[i] == 0; i++) ; /* Check zero filler */
|
||||||
if (i < BPB_ZeroedEx + 53)
|
if (i < BPB_ZeroedEx + 53) return FR_NO_FILESYSTEM;
|
||||||
return FR_NO_FILESYSTEM;
|
|
||||||
|
|
||||||
if (ld_word(fs->win + BPB_FSVerEx) != 0x100)
|
if (ld_word(fs->win + BPB_FSVerEx) != 0x100) return FR_NO_FILESYSTEM; /* Check exFAT version (must be version 1.0) */
|
||||||
return FR_NO_FILESYSTEM; /* Check exFAT version (must be version 1.0) */
|
|
||||||
|
|
||||||
if (1 << fs->win[BPB_BytsPerSecEx] != SS(fs)) { /* (BPB_BytsPerSecEx must be equal to the physical sector size) */
|
if (1 << fs->win[BPB_BytsPerSecEx] != SS(fs)) { /* (BPB_BytsPerSecEx must be equal to the physical sector size) */
|
||||||
EFSPRINTF("EXSPS");
|
EFSPRINTF("EXSPS");
|
||||||
|
@ -3315,8 +3326,7 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
||||||
}
|
}
|
||||||
|
|
||||||
maxlba = ld_qword(fs->win + BPB_TotSecEx) + bsect; /* Last LBA + 1 of the volume */
|
maxlba = ld_qword(fs->win + BPB_TotSecEx) + bsect; /* Last LBA + 1 of the volume */
|
||||||
if (maxlba >= 0x100000000)
|
if (maxlba >= 0x100000000) return FR_NO_FILESYSTEM; /* (It cannot be handled in 32-bit LBA) */
|
||||||
return FR_NO_FILESYSTEM; /* (It cannot be handled in 32-bit LBA) */
|
|
||||||
|
|
||||||
fs->fsize = ld_dword(fs->win + BPB_FatSzEx); /* Number of sectors per FAT */
|
fs->fsize = ld_dword(fs->win + BPB_FatSzEx); /* Number of sectors per FAT */
|
||||||
|
|
||||||
|
@ -3327,35 +3337,49 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
||||||
}
|
}
|
||||||
|
|
||||||
fs->csize = 1 << fs->win[BPB_SecPerClusEx]; /* Cluster size */
|
fs->csize = 1 << fs->win[BPB_SecPerClusEx]; /* Cluster size */
|
||||||
if (fs->csize == 0) {
|
if (fs->csize == 0) return FR_NO_FILESYSTEM; /* (Must be 1..32768) */
|
||||||
return FR_NO_FILESYSTEM; /* (Must be 1..32768) */
|
|
||||||
}
|
|
||||||
|
|
||||||
nclst = ld_dword(fs->win + BPB_NumClusEx); /* Number of clusters */
|
nclst = ld_dword(fs->win + BPB_NumClusEx); /* Number of clusters */
|
||||||
if (nclst > MAX_EXFAT)
|
if (nclst > MAX_EXFAT) return FR_NO_FILESYSTEM; /* (Too many clusters) */
|
||||||
return FR_NO_FILESYSTEM; /* (Too many clusters) */
|
|
||||||
fs->n_fatent = nclst + 2;
|
fs->n_fatent = nclst + 2;
|
||||||
|
|
||||||
/* Boundaries and Limits */
|
/* Boundaries and Limits */
|
||||||
fs->volbase = bsect;
|
fs->volbase = bsect;
|
||||||
fs->database = bsect + ld_dword(fs->win + BPB_DataOfsEx);
|
fs->database = bsect + ld_dword(fs->win + BPB_DataOfsEx);
|
||||||
fs->fatbase = bsect + ld_dword(fs->win + BPB_FatOfsEx);
|
fs->fatbase = bsect + ld_dword(fs->win + BPB_FatOfsEx);
|
||||||
if (maxlba < (QWORD)fs->database + nclst * fs->csize)
|
if (maxlba < (QWORD)fs->database + nclst * fs->csize) return FR_NO_FILESYSTEM; /* (Volume size must not be smaller than the size requiered) */
|
||||||
return FR_NO_FILESYSTEM; /* (Volume size must not be smaller than the size required) */
|
|
||||||
fs->dirbase = ld_dword(fs->win + BPB_RootClusEx);
|
fs->dirbase = ld_dword(fs->win + BPB_RootClusEx);
|
||||||
|
|
||||||
/* Check if bitmap location is in assumption (at the first cluster) */
|
/* Get bitmap location and check if it is contiguous (implementation assumption) */
|
||||||
if (move_window(fs, clst2sect(fs, fs->dirbase)) != FR_OK) {
|
so = i = 0;
|
||||||
EFSPRINTF("EXBM1C");
|
for (;;) { /* Find the bitmap entry in the root directory (in only first cluster) */
|
||||||
return FR_DISK_ERR;
|
if (i == 0) {
|
||||||
|
if (so >= fs->csize) return FR_NO_FILESYSTEM; /* Not found? */
|
||||||
|
if (move_window(fs, clst2sect(fs, fs->dirbase) + so) != FR_OK) {
|
||||||
|
EFSPRINTF("EXBM1C");
|
||||||
|
return FR_DISK_ERR;
|
||||||
|
}
|
||||||
|
so++;
|
||||||
|
}
|
||||||
|
if (fs->win[i] == ET_BITMAP) break; /* Is it a bitmap entry? */
|
||||||
|
i = (i + SZDIRE) % SS(fs); /* Next entry */
|
||||||
}
|
}
|
||||||
for (i = 0; i < SS(fs); i += SZDIRE) {
|
bcl = ld_dword(fs->win + i + 20); /* Bitmap cluster */
|
||||||
if (fs->win[i] == 0x81 && ld_dword(fs->win + i + 20) == 2) break; /* 81 entry with cluster #2? */
|
if (bcl < 2 || bcl >= fs->n_fatent) {
|
||||||
}
|
|
||||||
if (i == SS(fs)) {
|
|
||||||
EFSPRINTF("EXBMM");
|
EFSPRINTF("EXBMM");
|
||||||
return FR_NO_FILESYSTEM;
|
return FR_NO_FILESYSTEM;
|
||||||
}
|
}
|
||||||
|
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;
|
||||||
|
cv = ld_dword(fs->win + bcl % (SS(fs) / 4) * 4);
|
||||||
|
if (cv == 0xFFFFFFFF) break; /* Last link? */
|
||||||
|
if (cv != ++bcl) {
|
||||||
|
EFSPRINTF("EXBMM");
|
||||||
|
return FR_NO_FILESYSTEM; /* Fragmented? */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if !FF_FS_READONLY
|
#if !FF_FS_READONLY
|
||||||
fs->last_clst = fs->free_clst = 0xFFFFFFFF; /* Initialize cluster allocation information */
|
fs->last_clst = fs->free_clst = 0xFFFFFFFF; /* Initialize cluster allocation information */
|
||||||
#endif
|
#endif
|
||||||
|
@ -3373,38 +3397,31 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
||||||
fs->fsize = fasize;
|
fs->fsize = fasize;
|
||||||
|
|
||||||
fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FATs */
|
fs->n_fats = fs->win[BPB_NumFATs]; /* Number of FATs */
|
||||||
if (fs->n_fats != 1 && fs->n_fats != 2)
|
if (fs->n_fats != 1 && fs->n_fats != 2) return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */
|
||||||
return FR_NO_FILESYSTEM; /* (Must be 1 or 2) */
|
|
||||||
fasize *= fs->n_fats; /* Number of sectors for FAT area */
|
fasize *= fs->n_fats; /* Number of sectors for FAT area */
|
||||||
|
|
||||||
fs->csize = fs->win[BPB_SecPerClus]; /* Cluster size */
|
fs->csize = fs->win[BPB_SecPerClus]; /* Cluster size */
|
||||||
if (fs->csize == 0 || (fs->csize & (fs->csize - 1)))
|
if (fs->csize == 0 || (fs->csize & (fs->csize - 1))) return FR_NO_FILESYSTEM; /* (Must be power of 2) */
|
||||||
return FR_NO_FILESYSTEM; /* (Must be power of 2) */
|
|
||||||
|
|
||||||
fs->n_rootdir = ld_word(fs->win + BPB_RootEntCnt); /* Number of root directory entries */
|
fs->n_rootdir = ld_word(fs->win + BPB_RootEntCnt); /* Number of root directory entries */
|
||||||
if (fs->n_rootdir % (SS(fs) / SZDIRE))
|
if (fs->n_rootdir % (SS(fs) / SZDIRE)) return FR_NO_FILESYSTEM; /* (Must be sector aligned) */
|
||||||
return FR_NO_FILESYSTEM; /* (Must be sector aligned) */
|
|
||||||
|
|
||||||
tsect = ld_word(fs->win + BPB_TotSec16); /* Number of sectors on the volume */
|
tsect = ld_word(fs->win + BPB_TotSec16); /* Number of sectors on the volume */
|
||||||
if (tsect == 0) tsect = ld_dword(fs->win + BPB_TotSec32);
|
if (tsect == 0) tsect = ld_dword(fs->win + BPB_TotSec32);
|
||||||
|
|
||||||
nrsv = ld_word(fs->win + BPB_RsvdSecCnt); /* Number of reserved sectors */
|
nrsv = ld_word(fs->win + BPB_RsvdSecCnt); /* Number of reserved sectors */
|
||||||
if (nrsv == 0)
|
if (nrsv == 0) return FR_NO_FILESYSTEM; /* (Must not be 0) */
|
||||||
return FR_NO_FILESYSTEM; /* (Must not be 0) */
|
|
||||||
|
|
||||||
/* Determine the FAT sub type */
|
/* Determine the FAT sub type */
|
||||||
sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZDIRE); /* RSV + FAT + DIR */
|
sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZDIRE); /* RSV + FAT + DIR */
|
||||||
if (tsect < sysect)
|
if (tsect < sysect) return FR_NO_FILESYSTEM; /* (Invalid volume size) */
|
||||||
return FR_NO_FILESYSTEM; /* (Invalid volume size) */
|
|
||||||
nclst = (tsect - sysect) / fs->csize; /* Number of clusters */
|
nclst = (tsect - sysect) / fs->csize; /* Number of clusters */
|
||||||
if (nclst == 0)
|
if (nclst == 0) return FR_NO_FILESYSTEM; /* (Invalid volume size) */
|
||||||
return FR_NO_FILESYSTEM; /* (Invalid volume size) */
|
|
||||||
fmt = 0;
|
fmt = 0;
|
||||||
if (nclst <= MAX_FAT32) fmt = FS_FAT32;
|
if (nclst <= MAX_FAT32) fmt = FS_FAT32;
|
||||||
if (nclst <= MAX_FAT16) fmt = FS_FAT16;
|
if (nclst <= MAX_FAT16) fmt = FS_FAT16;
|
||||||
if (nclst <= MAX_FAT12) fmt = FS_FAT12;
|
if (nclst <= MAX_FAT12) fmt = FS_FAT12;
|
||||||
if (fmt == 0)
|
if (fmt == 0) return FR_NO_FILESYSTEM;
|
||||||
return FR_NO_FILESYSTEM;
|
|
||||||
|
|
||||||
/* Boundaries and Limits */
|
/* Boundaries and Limits */
|
||||||
fs->n_fatent = nclst + 2; /* Number of FAT entries */
|
fs->n_fatent = nclst + 2; /* Number of FAT entries */
|
||||||
|
@ -3412,21 +3429,17 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
||||||
fs->fatbase = bsect + nrsv; /* FAT start sector */
|
fs->fatbase = bsect + nrsv; /* FAT start sector */
|
||||||
fs->database = bsect + sysect; /* Data start sector */
|
fs->database = bsect + sysect; /* Data start sector */
|
||||||
if (fmt == FS_FAT32) {
|
if (fmt == FS_FAT32) {
|
||||||
if (ld_word(fs->win + BPB_FSVer32) != 0)
|
if (ld_word(fs->win + BPB_FSVer32) != 0) return FR_NO_FILESYSTEM; /* (Must be FAT32 revision 0.0) */
|
||||||
return FR_NO_FILESYSTEM; /* (Must be FAT32 revision 0.0) */
|
if (fs->n_rootdir != 0) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */
|
||||||
if (fs->n_rootdir != 0)
|
|
||||||
return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must be 0) */
|
|
||||||
fs->dirbase = ld_dword(fs->win + BPB_RootClus32); /* Root directory start cluster */
|
fs->dirbase = ld_dword(fs->win + BPB_RootClus32); /* Root directory start cluster */
|
||||||
szbfat = fs->n_fatent * 4; /* (Needed FAT size) */
|
szbfat = fs->n_fatent * 4; /* (Needed FAT size) */
|
||||||
} else {
|
} else {
|
||||||
if (fs->n_rootdir == 0)
|
if (fs->n_rootdir == 0) return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */
|
||||||
return FR_NO_FILESYSTEM; /* (BPB_RootEntCnt must not be 0) */
|
|
||||||
fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */
|
fs->dirbase = fs->fatbase + fasize; /* Root directory start sector */
|
||||||
szbfat = (fmt == FS_FAT16) ? /* (Needed FAT size) */
|
szbfat = (fmt == FS_FAT16) ? /* (Needed FAT size) */
|
||||||
fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1);
|
fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1);
|
||||||
}
|
}
|
||||||
if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs))
|
if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) return FR_NO_FILESYSTEM; /* (BPB_FATSz must not be less than the size needed) */
|
||||||
return FR_NO_FILESYSTEM; /* (BPB_FATSz must not be less than the size needed) */
|
|
||||||
|
|
||||||
#if !FF_FS_READONLY
|
#if !FF_FS_READONLY
|
||||||
/* Get FSInfo if available */
|
/* Get FSInfo if available */
|
||||||
|
@ -3459,7 +3472,7 @@ static FRESULT find_volume ( /* FR_OK(0): successful, !=0: an error occurred */
|
||||||
#if FF_USE_LFN == 1
|
#if FF_USE_LFN == 1
|
||||||
fs->lfnbuf = LfnBuf; /* Static LFN working buffer */
|
fs->lfnbuf = LfnBuf; /* Static LFN working buffer */
|
||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
fs->dirbuf = DirBuf; /* Static directory block scratchpad buffer */
|
fs->dirbuf = DirBuf; /* Static directory block scratchpad buuffer */
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#if FF_FS_RPATH != 0
|
#if FF_FS_RPATH != 0
|
||||||
|
@ -3722,7 +3735,7 @@ FRESULT f_open (
|
||||||
fp->fptr = 0; /* Set file pointer top of the file */
|
fp->fptr = 0; /* Set file pointer top of the file */
|
||||||
#if !FF_FS_READONLY
|
#if !FF_FS_READONLY
|
||||||
#if !FF_FS_TINY
|
#if !FF_FS_TINY
|
||||||
mem_set(fp->buf, 0, FF_MAX_SS); /* Clear sector buffer */
|
mem_set(fp->buf, 0, sizeof fp->buf); /* Clear sector buffer */
|
||||||
#endif
|
#endif
|
||||||
if ((mode & FA_SEEKEND) && fp->obj.objsize > 0) { /* Seek to end of file if FA_OPEN_APPEND is specified */
|
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 */
|
fp->fptr = fp->obj.objsize; /* Offset to seek */
|
||||||
|
@ -3819,9 +3832,7 @@ FRESULT f_read (
|
||||||
fp->clust = clst; /* Update current cluster */
|
fp->clust = clst; /* Update current cluster */
|
||||||
}
|
}
|
||||||
sect = clst2sect(fs, fp->clust); /* Get current sector */
|
sect = clst2sect(fs, fp->clust); /* Get current sector */
|
||||||
if (sect == 0) {
|
if (sect == 0) ABORT(fs, FR_INT_ERR);
|
||||||
ABORT(fs, FR_INT_ERR);
|
|
||||||
}
|
|
||||||
sect += csect;
|
sect += csect;
|
||||||
cc = btr / SS(fs); /* When remaining bytes >= sector size, */
|
cc = btr / SS(fs); /* When remaining bytes >= sector size, */
|
||||||
if (cc > 0) { /* Read maximum contiguous sectors directly */
|
if (cc > 0) { /* Read maximum contiguous sectors directly */
|
||||||
|
@ -3906,10 +3917,7 @@ FRESULT f_write (
|
||||||
EFSPRINTF("FOV");
|
EFSPRINTF("FOV");
|
||||||
LEAVE_FF(fs, res); /* Check validity */
|
LEAVE_FF(fs, res); /* Check validity */
|
||||||
}
|
}
|
||||||
if (!(fp->flag & FA_WRITE)) {
|
if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED); /* Check access mode */
|
||||||
EFSPRINTF("NOACCESS");
|
|
||||||
LEAVE_FF(fs, FR_DENIED); /* Check access mode */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Check fptr wrap-around (file size cannot reach 4 GiB at FAT volume) */
|
/* Check fptr wrap-around (file size cannot reach 4 GiB at FAT volume) */
|
||||||
if ((!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) && (DWORD)(fp->fptr + btw) < (DWORD)fp->fptr) {
|
if ((!FF_FS_EXFAT || fs->fs_type != FS_EXFAT) && (DWORD)(fp->fptr + btw) < (DWORD)fp->fptr) {
|
||||||
|
@ -3955,15 +3963,12 @@ FRESULT f_write (
|
||||||
if (fs->winsect == fp->sect && sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Write-back sector cache */
|
if (fs->winsect == fp->sect && sync_window(fs) != FR_OK) ABORT(fs, FR_DISK_ERR); /* Write-back sector cache */
|
||||||
#else
|
#else
|
||||||
if (fp->flag & FA_DIRTY) { /* Write-back sector cache */
|
if (fp->flag & FA_DIRTY) { /* Write-back sector cache */
|
||||||
if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK)
|
if (disk_write(fs->pdrv, fp->buf, fp->sect, 1) != RES_OK) ABORT(fs, FR_DISK_ERR);
|
||||||
ABORT(fs, FR_DISK_ERR);
|
|
||||||
fp->flag &= (BYTE)~FA_DIRTY;
|
fp->flag &= (BYTE)~FA_DIRTY;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
sect = clst2sect(fs, fp->clust); /* Get current sector */
|
sect = clst2sect(fs, fp->clust); /* Get current sector */
|
||||||
if (sect == 0) {
|
if (sect == 0) ABORT(fs, FR_INT_ERR);
|
||||||
ABORT(fs, FR_INT_ERR);
|
|
||||||
}
|
|
||||||
sect += csect;
|
sect += csect;
|
||||||
cc = btw / SS(fs); /* When remaining bytes >= sector size, */
|
cc = btw / SS(fs); /* When remaining bytes >= sector size, */
|
||||||
if (cc > 0) { /* Write maximum contiguous sectors directly */
|
if (cc > 0) { /* Write maximum contiguous sectors directly */
|
||||||
|
@ -3998,8 +4003,9 @@ FRESULT f_write (
|
||||||
#else
|
#else
|
||||||
if (fp->sect != sect && /* Fill sector cache with file data */
|
if (fp->sect != sect && /* Fill sector cache with file data */
|
||||||
fp->fptr < fp->obj.objsize &&
|
fp->fptr < fp->obj.objsize &&
|
||||||
disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK)
|
disk_read(fs->pdrv, fp->buf, sect, 1) != RES_OK) {
|
||||||
ABORT(fs, FR_DISK_ERR);
|
ABORT(fs, FR_DISK_ERR);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
fp->sect = sect;
|
fp->sect = sect;
|
||||||
}
|
}
|
||||||
|
@ -4245,6 +4251,7 @@ FRESULT f_getcwd (
|
||||||
|
|
||||||
|
|
||||||
/* Get logical drive */
|
/* Get logical drive */
|
||||||
|
buff[0] = 0; /* Set null string to get current volume */
|
||||||
res = find_volume((const TCHAR**)&buff, &fs, 0); /* Get current volume */
|
res = find_volume((const TCHAR**)&buff, &fs, 0); /* Get current volume */
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
dj.obj.fs = fs;
|
dj.obj.fs = fs;
|
||||||
|
@ -4263,7 +4270,7 @@ FRESULT f_getcwd (
|
||||||
res = dir_sdi(&dj, 0);
|
res = dir_sdi(&dj, 0);
|
||||||
if (res != FR_OK) break;
|
if (res != FR_OK) break;
|
||||||
do { /* Find the entry links to the child directory */
|
do { /* Find the entry links to the child directory */
|
||||||
res = dir_read_file(&dj);
|
res = DIR_READ_FILE(&dj);
|
||||||
if (res != FR_OK) break;
|
if (res != FR_OK) break;
|
||||||
if (ccl == ld_clust(fs, dj.dir)) break; /* Found the entry */
|
if (ccl == ld_clust(fs, dj.dir)) break; /* Found the entry */
|
||||||
res = dir_next(&dj, 0);
|
res = dir_next(&dj, 0);
|
||||||
|
@ -4595,7 +4602,7 @@ FRESULT f_readdir (
|
||||||
res = dir_sdi(dp, 0); /* Rewind the directory object */
|
res = dir_sdi(dp, 0); /* Rewind the directory object */
|
||||||
} else {
|
} else {
|
||||||
INIT_NAMBUF(fs);
|
INIT_NAMBUF(fs);
|
||||||
res = dir_read_file(dp); /* Read an item */
|
res = DIR_READ_FILE(dp); /* Read an item */
|
||||||
if (res == FR_NO_FILE) res = FR_OK; /* Ignore end of directory */
|
if (res == FR_NO_FILE) res = FR_OK; /* Ignore end of directory */
|
||||||
if (res == FR_OK) { /* A valid entry is found */
|
if (res == FR_OK) { /* A valid entry is found */
|
||||||
get_fileinfo(dp, fno); /* Get the object information */
|
get_fileinfo(dp, fno); /* Get the object information */
|
||||||
|
@ -4740,7 +4747,7 @@ FRESULT f_getfree (
|
||||||
UINT b;
|
UINT b;
|
||||||
|
|
||||||
clst = fs->n_fatent - 2; /* Number of clusters */
|
clst = fs->n_fatent - 2; /* Number of clusters */
|
||||||
sect = fs->database; /* Assuming bitmap starts at cluster 2 */
|
sect = fs->bitbase; /* Bitmap sector */
|
||||||
i = 0; /* Offset in the sector */
|
i = 0; /* Offset in the sector */
|
||||||
do { /* Counts numbuer of bits with zero in the bitmap */
|
do { /* Counts numbuer of bits with zero in the bitmap */
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
|
@ -4903,7 +4910,7 @@ FRESULT f_unlink (
|
||||||
#endif
|
#endif
|
||||||
res = dir_sdi(&sdj, 0);
|
res = dir_sdi(&sdj, 0);
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
res = dir_read_file(&sdj); /* Test if the directory is empty */
|
res = DIR_READ_FILE(&sdj); /* Test if the directory is empty */
|
||||||
if (res == FR_OK) res = FR_DENIED; /* Not empty? */
|
if (res == FR_OK) res = FR_DENIED; /* Not empty? */
|
||||||
if (res == FR_NO_FILE) res = FR_OK; /* Empty? */
|
if (res == FR_NO_FILE) res = FR_OK; /* Empty? */
|
||||||
}
|
}
|
||||||
|
@ -4943,47 +4950,43 @@ FRESULT f_mkdir (
|
||||||
DIR dj;
|
DIR dj;
|
||||||
FFOBJID sobj;
|
FFOBJID sobj;
|
||||||
FATFS *fs;
|
FATFS *fs;
|
||||||
BYTE *dir;
|
|
||||||
DWORD dcl, pcl, tm;
|
DWORD dcl, pcl, tm;
|
||||||
DEF_NAMBUF
|
DEF_NAMBUF
|
||||||
|
|
||||||
|
|
||||||
/* Get logical drive */
|
res = find_volume(&path, &fs, FA_WRITE); /* Get logical drive */
|
||||||
res = find_volume(&path, &fs, FA_WRITE);
|
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
dj.obj.fs = fs;
|
dj.obj.fs = fs;
|
||||||
INIT_NAMBUF(fs);
|
INIT_NAMBUF(fs);
|
||||||
res = follow_path(&dj, path); /* Follow the file path */
|
res = follow_path(&dj, path); /* Follow the file path */
|
||||||
if (res == FR_OK) res = FR_EXIST; /* Any object with same name is already existing */
|
if (res == FR_OK) res = FR_EXIST; /* Name collision? */
|
||||||
if (FF_FS_RPATH && res == FR_NO_FILE && (dj.fn[NSFLAG] & NS_DOT)) {
|
if (FF_FS_RPATH && res == FR_NO_FILE && (dj.fn[NSFLAG] & NS_DOT)) { /* Invalid name? */
|
||||||
res = FR_INVALID_NAME;
|
res = FR_INVALID_NAME;
|
||||||
}
|
}
|
||||||
if (res == FR_NO_FILE) { /* Can create a new directory */
|
if (res == FR_NO_FILE) { /* It is clear to create a new directory */
|
||||||
sobj.fs = fs; /* New object id to create a new chain */
|
sobj.fs = fs; /* New object id to create a new chain */
|
||||||
dcl = create_chain(&sobj, 0); /* Allocate a cluster for the new directory */
|
dcl = create_chain(&sobj, 0); /* Allocate a cluster for the new directory */
|
||||||
res = FR_OK;
|
res = FR_OK;
|
||||||
if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster */
|
if (dcl == 0) res = FR_DENIED; /* No space to allocate a new cluster? */
|
||||||
if (dcl == 1) res = FR_INT_ERR;
|
if (dcl == 1) res = FR_INT_ERR; /* Any insanity? */
|
||||||
if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR;
|
if (dcl == 0xFFFFFFFF) res = FR_DISK_ERR; /* Disk error? */
|
||||||
if (res == FR_OK) res = sync_window(fs); /* Flush FAT */
|
|
||||||
tm = GET_FATTIME();
|
tm = GET_FATTIME();
|
||||||
if (res == FR_OK) { /* Initialize the new directory table */
|
|
||||||
res = dir_clear(fs, dcl); /* Clean up the new table */
|
|
||||||
if (res == FR_OK && (!FF_FS_EXFAT || fs->fs_type != FS_EXFAT)) { /* Create dot entries (FAT only) */
|
|
||||||
dir = fs->win;
|
|
||||||
mem_set(dir + DIR_Name, ' ', 11); /* Create "." entry */
|
|
||||||
dir[DIR_Name] = '.';
|
|
||||||
dir[DIR_Attr] = AM_DIR;
|
|
||||||
st_dword(dir + DIR_ModTime, tm);
|
|
||||||
st_clust(fs, dir, dcl);
|
|
||||||
mem_cpy(dir + SZDIRE, dir, SZDIRE); /* Create ".." entry */
|
|
||||||
dir[SZDIRE + 1] = '.'; pcl = dj.obj.sclust;
|
|
||||||
st_clust(fs, dir + SZDIRE, pcl);
|
|
||||||
fs->wflag = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
res = dir_register(&dj); /* Register the object to the directoy */
|
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 */
|
||||||
|
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 */
|
||||||
|
fs->win[SZDIRE + 1] = '.'; pcl = dj.obj.sclust;
|
||||||
|
st_clust(fs, fs->win + SZDIRE, pcl);
|
||||||
|
fs->wflag = 1;
|
||||||
|
}
|
||||||
|
res = dir_register(&dj); /* Register the object to the parent directoy */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
|
@ -4998,17 +5001,16 @@ FRESULT f_mkdir (
|
||||||
} else
|
} else
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
dir = dj.dir;
|
st_dword(dj.dir + DIR_ModTime, tm); /* Created time */
|
||||||
st_dword(dir + DIR_ModTime, tm); /* Created time */
|
st_clust(fs, dj.dir, dcl); /* Table start cluster */
|
||||||
st_clust(fs, dir, dcl); /* Table start cluster */
|
dj.dir[DIR_Attr] = AM_DIR; /* Attribute */
|
||||||
dir[DIR_Attr] = AM_DIR; /* Attribute */
|
|
||||||
fs->wflag = 1;
|
fs->wflag = 1;
|
||||||
}
|
}
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
res = sync_fs(fs);
|
res = sync_fs(fs);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
remove_chain(&dj.obj, dcl, 0); /* Could not register, remove cluster chain */
|
remove_chain(&sobj, dcl, 0); /* Could not register, remove the allocated cluster */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FREE_NAMBUF();
|
FREE_NAMBUF();
|
||||||
|
@ -5248,7 +5250,7 @@ FRESULT f_getlabel (
|
||||||
dj.obj.fs = fs; dj.obj.sclust = 0; /* Open root directory */
|
dj.obj.fs = fs; dj.obj.sclust = 0; /* Open root directory */
|
||||||
res = dir_sdi(&dj, 0);
|
res = dir_sdi(&dj, 0);
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
res = dir_read_label(&dj); /* Find a volume label entry */
|
res = DIR_READ_LABEL(&dj); /* Find a volume label entry */
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
if (fs->fs_type == FS_EXFAT) {
|
if (fs->fs_type == FS_EXFAT) {
|
||||||
|
@ -5393,7 +5395,7 @@ FRESULT f_setlabel (
|
||||||
dj.obj.fs = fs; dj.obj.sclust = 0; /* Open root directory */
|
dj.obj.fs = fs; dj.obj.sclust = 0; /* Open root directory */
|
||||||
res = dir_sdi(&dj, 0);
|
res = dir_sdi(&dj, 0);
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
res = dir_read_label(&dj); /* Get volume label entry */
|
res = DIR_READ_LABEL(&dj); /* Get volume label entry */
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) {
|
if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) {
|
||||||
dj.dir[XDIR_NumLabel] = (BYTE)di; /* Change the volume label */
|
dj.dir[XDIR_NumLabel] = (BYTE)di; /* Change the volume label */
|
||||||
|
@ -5415,7 +5417,7 @@ FRESULT f_setlabel (
|
||||||
if (res == FR_OK) {
|
if (res == FR_OK) {
|
||||||
mem_set(dj.dir, 0, SZDIRE); /* Clean the entry */
|
mem_set(dj.dir, 0, SZDIRE); /* Clean the entry */
|
||||||
if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) {
|
if (FF_FS_EXFAT && fs->fs_type == FS_EXFAT) {
|
||||||
dj.dir[XDIR_Type] = 0x83; /* Create 83 entry */
|
dj.dir[XDIR_Type] = ET_VLABEL; /* Create volume label entry */
|
||||||
dj.dir[XDIR_NumLabel] = (BYTE)di;
|
dj.dir[XDIR_NumLabel] = (BYTE)di;
|
||||||
mem_cpy(dj.dir + XDIR_Label, dirvn, 22);
|
mem_cpy(dj.dir + XDIR_Label, dirvn, 22);
|
||||||
} else {
|
} else {
|
||||||
|
@ -5720,7 +5722,7 @@ FRESULT f_mkfs (
|
||||||
b_fat = b_vol + 32; /* FAT start at offset 32 */
|
b_fat = b_vol + 32; /* FAT start at offset 32 */
|
||||||
sz_fat = ((sz_vol / au + 2) * 4 + ss - 1) / ss; /* Number of FAT sectors */
|
sz_fat = ((sz_vol / au + 2) * 4 + ss - 1) / ss; /* Number of FAT sectors */
|
||||||
b_data = (b_fat + sz_fat + sz_blk - 1) & ~(sz_blk - 1); /* Align data area to the erase block boundary */
|
b_data = (b_fat + sz_fat + sz_blk - 1) & ~(sz_blk - 1); /* Align data area to the erase block boundary */
|
||||||
if (b_data >= sz_vol / 2) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume? */
|
if (b_data - b_vol >= sz_vol / 2) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too small volume? */
|
||||||
n_clst = (sz_vol - (b_data - b_vol)) / au; /* Number of clusters */
|
n_clst = (sz_vol - (b_data - b_vol)) / au; /* Number of clusters */
|
||||||
if (n_clst <16) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too few 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? */
|
if (n_clst > MAX_EXFAT) LEAVE_MKFS(FR_MKFS_ABORTED); /* Too many clusters? */
|
||||||
|
@ -5801,11 +5803,11 @@ FRESULT f_mkfs (
|
||||||
|
|
||||||
/* Initialize the root directory */
|
/* Initialize the root directory */
|
||||||
mem_set(buf, 0, szb_buf);
|
mem_set(buf, 0, szb_buf);
|
||||||
buf[SZDIRE * 0 + 0] = 0x83; /* 83 entry (volume label) */
|
buf[SZDIRE * 0 + 0] = ET_VLABEL; /* Volume label entry */
|
||||||
buf[SZDIRE * 1 + 0] = 0x81; /* 81 entry (allocation bitmap) */
|
buf[SZDIRE * 1 + 0] = ET_BITMAP; /* Bitmap entry */
|
||||||
st_dword(buf + SZDIRE * 1 + 20, 2); /* cluster */
|
st_dword(buf + SZDIRE * 1 + 20, 2); /* cluster */
|
||||||
st_dword(buf + SZDIRE * 1 + 24, szb_bit); /* size */
|
st_dword(buf + SZDIRE * 1 + 24, szb_bit); /* size */
|
||||||
buf[SZDIRE * 2 + 0] = 0x82; /* 82 entry (up-case table) */
|
buf[SZDIRE * 2 + 0] = ET_UPCASE; /* Up-case table entry */
|
||||||
st_dword(buf + SZDIRE * 2 + 4, sum); /* sum */
|
st_dword(buf + SZDIRE * 2 + 4, sum); /* sum */
|
||||||
st_dword(buf + SZDIRE * 2 + 20, 2 + tbl[0]); /* cluster */
|
st_dword(buf + SZDIRE * 2 + 20, 2 + tbl[0]); /* cluster */
|
||||||
st_dword(buf + SZDIRE * 2 + 24, szb_case); /* size */
|
st_dword(buf + SZDIRE * 2 + 24, szb_case); /* size */
|
||||||
|
@ -6293,8 +6295,7 @@ typedef struct { /* Putchar output buffer and work area */
|
||||||
} putbuff;
|
} putbuff;
|
||||||
|
|
||||||
|
|
||||||
static
|
static void putc_bfd ( /* Buffered write with code conversion */
|
||||||
void putc_bfd ( /* Buffered write with code conversion */
|
|
||||||
putbuff* pb,
|
putbuff* pb,
|
||||||
TCHAR c
|
TCHAR c
|
||||||
)
|
)
|
||||||
|
@ -6405,7 +6406,7 @@ void putc_bfd ( /* Buffered write with code conversion */
|
||||||
#else /* Write it in ANSI/OEM */
|
#else /* Write it in ANSI/OEM */
|
||||||
if (hs != 0) return;
|
if (hs != 0) return;
|
||||||
wc = ff_uni2oem(wc, CODEPAGE); /* UTF-16 ==> ANSI/OEM */
|
wc = ff_uni2oem(wc, CODEPAGE); /* UTF-16 ==> ANSI/OEM */
|
||||||
if (wc == 0) return;;
|
if (wc == 0) return;
|
||||||
if (wc >= 0x100) {
|
if (wc >= 0x100) {
|
||||||
pb->buf[i++] = (BYTE)(wc >> 8); nc++;
|
pb->buf[i++] = (BYTE)(wc >> 8); nc++;
|
||||||
}
|
}
|
||||||
|
@ -6425,8 +6426,7 @@ void putc_bfd ( /* Buffered write with code conversion */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static
|
static int putc_flush ( /* Flush left characters in the buffer */
|
||||||
int putc_flush ( /* Flush left characters in the buffer */
|
|
||||||
putbuff* pb
|
putbuff* pb
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -6439,8 +6439,7 @@ int putc_flush ( /* Flush left characters in the buffer */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static
|
static void putc_init ( /* Initialize write buffer */
|
||||||
void putc_init ( /* Initialize write buffer */
|
|
||||||
putbuff* pb,
|
putbuff* pb,
|
||||||
FIL* fp
|
FIL* fp
|
||||||
)
|
)
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*----------------------------------------------------------------------------/
|
/*----------------------------------------------------------------------------/
|
||||||
/ FatFs - Generic FAT Filesystem module R0.13b /
|
/ FatFs - Generic FAT Filesystem module R0.13c /
|
||||||
/-----------------------------------------------------------------------------/
|
/-----------------------------------------------------------------------------/
|
||||||
/
|
/
|
||||||
/ Copyright (C) 2018, ChaN, all right reserved.
|
/ Copyright (C) 2018, ChaN, all right reserved.
|
||||||
|
@ -20,7 +20,7 @@
|
||||||
|
|
||||||
|
|
||||||
#ifndef FF_DEFINED
|
#ifndef FF_DEFINED
|
||||||
#define FF_DEFINED 63463 /* Revision ID */
|
#define FF_DEFINED 86604 /* Revision ID */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
@ -95,8 +95,8 @@ typedef DWORD FSIZE_t;
|
||||||
/* Filesystem object structure (FATFS) */
|
/* Filesystem object structure (FATFS) */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
BYTE fs_type; /* Filesystem type (0:N/A) */
|
BYTE fs_type; /* Filesystem type (0:not mounted) */
|
||||||
BYTE pdrv; /* Physical drive number */
|
BYTE pdrv; /* Associated physical drive */
|
||||||
BYTE n_fats; /* Number of FATs (1 or 2) */
|
BYTE n_fats; /* Number of FATs (1 or 2) */
|
||||||
BYTE wflag; /* win[] flag (b0:dirty) */
|
BYTE wflag; /* win[] flag (b0:dirty) */
|
||||||
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
|
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
|
||||||
|
@ -133,6 +133,9 @@ typedef struct {
|
||||||
DWORD fatbase; /* FAT base sector */
|
DWORD fatbase; /* FAT base sector */
|
||||||
DWORD dirbase; /* Root directory base sector/cluster */
|
DWORD dirbase; /* Root directory base sector/cluster */
|
||||||
DWORD database; /* Data base sector */
|
DWORD database; /* Data base sector */
|
||||||
|
#if FF_FS_EXFAT
|
||||||
|
DWORD bitbase; /* Allocation bitmap base sector */
|
||||||
|
#endif
|
||||||
DWORD winsect; /* Current sector appearing in the win[] */
|
DWORD winsect; /* Current sector appearing in the win[] */
|
||||||
BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
|
BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
|
||||||
} FATFS;
|
} FATFS;
|
||||||
|
@ -145,7 +148,7 @@ typedef struct {
|
||||||
FATFS* fs; /* Pointer to the hosting volume of this object */
|
FATFS* fs; /* Pointer to the hosting volume of this object */
|
||||||
WORD id; /* Hosting volume mount ID */
|
WORD id; /* Hosting volume mount ID */
|
||||||
BYTE attr; /* Object attribute */
|
BYTE attr; /* Object attribute */
|
||||||
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:flagmented in this session, b2:sub-directory stretched) */
|
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) */
|
DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */
|
||||||
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
|
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
|
||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
/*---------------------------------------------------------------------------/
|
/*---------------------------------------------------------------------------/
|
||||||
/ FatFs - Configuration file
|
/ FatFs Functional Configurations
|
||||||
/---------------------------------------------------------------------------*/
|
/---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#define FFCONF_DEF 63463 /* Revision ID */
|
#define FFCONF_DEF 86604 /* Revision ID */
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------/
|
/*---------------------------------------------------------------------------/
|
||||||
/ Function Configurations
|
/ Function Configurations
|
||||||
|
@ -232,7 +232,7 @@
|
||||||
|
|
||||||
#define FF_FS_EXFAT 1
|
#define FF_FS_EXFAT 1
|
||||||
/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
|
/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
|
||||||
/ To enable exFAT, also LFN needs to be enabled.
|
/ To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1)
|
||||||
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */
|
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */
|
||||||
|
|
||||||
|
|
||||||
|
@ -262,6 +262,7 @@
|
||||||
/ lock control is independent of re-entrancy. */
|
/ lock control is independent of re-entrancy. */
|
||||||
|
|
||||||
|
|
||||||
|
/* #include <somertos.h> // O/S definitions */
|
||||||
#define FF_FS_REENTRANT 0
|
#define FF_FS_REENTRANT 0
|
||||||
#define FF_FS_TIMEOUT 1000
|
#define FF_FS_TIMEOUT 1000
|
||||||
#define FF_SYNC_t HANDLE
|
#define FF_SYNC_t HANDLE
|
||||||
|
@ -282,8 +283,6 @@
|
||||||
/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
|
/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
|
||||||
/ included somewhere in the scope of ff.h. */
|
/ included somewhere in the scope of ff.h. */
|
||||||
|
|
||||||
/* #include <windows.h> // O/S definitions */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*--- End of configuration options ---*/
|
/*--- End of configuration options ---*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
/* Sample Code of OS Dependent Functions for FatFs */
|
/* Sample Code of OS Dependent Functions for FatFs */
|
||||||
/* (C) ChaN, 2017 */
|
/* (C) ChaN, 2018 */
|
||||||
/* (C) CTCaer, 2018 */
|
/* (C) CTCaer, 2018 */
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@
|
||||||
/* Allocate a memory block */
|
/* Allocate a memory block */
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void* ff_memalloc ( /* Returns pointer to the allocated memory block (null on not enough core) */
|
void* ff_memalloc ( /* Returns pointer to the allocated memory block (null if not enough core) */
|
||||||
UINT msize /* Number of bytes to allocate */
|
UINT msize /* Number of bytes to allocate */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
@ -29,7 +29,7 @@ void* ff_memalloc ( /* Returns pointer to the allocated memory block (null on no
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void ff_memfree (
|
void ff_memfree (
|
||||||
void* mblock /* Pointer to the memory block to free (nothing to do for null) */
|
void* mblock /* Pointer to the memory block to free (nothing to do if null) */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
free(mblock); /* Free the memory block with POSIX API */
|
free(mblock); /* Free the memory block with POSIX API */
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
/* Unicode handling functions for FatFs R0.13a */
|
/* Unicode handling functions for FatFs R0.13c */
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
/* This module will occupy a huge memory in the .const section when the /
|
/* 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 /
|
/ FatFs is configured for LFN with DBCS. If the system has any Unicode /
|
||||||
|
@ -7,7 +7,7 @@
|
||||||
/ that function to avoid silly memory consumption. /
|
/ that function to avoid silly memory consumption. /
|
||||||
/-------------------------------------------------------------------------*/
|
/-------------------------------------------------------------------------*/
|
||||||
/*
|
/*
|
||||||
/ Copyright (C) 2017, ChaN, all right reserved.
|
/ Copyright (C) 2018, ChaN, all right reserved.
|
||||||
/
|
/
|
||||||
/ FatFs module is an open source software. Redistribution and use of FatFs in
|
/ FatFs module is an open source software. Redistribution and use of FatFs in
|
||||||
/ source and binary forms, with or without modification, are permitted provided
|
/ source and binary forms, with or without modification, are permitted provided
|
||||||
|
@ -25,9 +25,9 @@
|
||||||
|
|
||||||
#include "ff.h"
|
#include "ff.h"
|
||||||
|
|
||||||
#if FF_USE_LFN /* This module is blanked when non-LFN configuration */
|
#if FF_USE_LFN /* This module will be blanked at non-LFN configuration */
|
||||||
|
|
||||||
#if FF_DEFINED != 63463 /* Revision ID */
|
#if FF_DEFINED != 86604 /* Revision ID */
|
||||||
#error Wrong include file (ff.h).
|
#error Wrong include file (ff.h).
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue