From c4aeb6d5abc2a42f69388e33394a6f43740486ef Mon Sep 17 00:00:00 2001
From: Dean Camera <dean@fourwalledcubicle.com>
Date: Sat, 1 Sep 2012 22:55:15 +0000
Subject: [PATCH] Update FatFS library copies to the latest R0.09a version.

---
 .../TempDataLogger/Lib/FATFs/00readme.txt     |  14 +-
 Projects/TempDataLogger/Lib/FATFs/diskio.c    |   4 +-
 Projects/TempDataLogger/Lib/FATFs/diskio.h    |  30 +-
 Projects/TempDataLogger/Lib/FATFs/ff.c        | 748 ++++++++++-------
 Projects/TempDataLogger/Lib/FATFs/ff.h        |  71 +-
 Projects/TempDataLogger/Lib/FATFs/ffconf.h    |  17 +-
 Projects/Webserver/Lib/FATFs/00readme.txt     |  14 +-
 Projects/Webserver/Lib/FATFs/diskio.c         |   4 +-
 Projects/Webserver/Lib/FATFs/diskio.h         |  14 +-
 Projects/Webserver/Lib/FATFs/ff.c             | 750 +++++++++++-------
 Projects/Webserver/Lib/FATFs/ff.h             |  65 +-
 Projects/Webserver/Lib/FATFs/ffconf.h         |  14 +-
 12 files changed, 1035 insertions(+), 710 deletions(-)

diff --git a/Projects/TempDataLogger/Lib/FATFs/00readme.txt b/Projects/TempDataLogger/Lib/FATFs/00readme.txt
index c78da3186..80d8843d1 100644
--- a/Projects/TempDataLogger/Lib/FATFs/00readme.txt
+++ b/Projects/TempDataLogger/Lib/FATFs/00readme.txt
@@ -1,4 +1,4 @@
-FatFs Module Source Files R0.08b                       (C)ChaN, 2011
+FatFs Module Source Files R0.09a                       (C)ChaN, 2012
 
 
 FILES
@@ -7,7 +7,8 @@ FILES
   ff.h       Common include file for FatFs and application module.
   ff.c       FatFs module.
   diskio.h   Common include file for FatFs and disk I/O module.
-  integer.h  Alternative type definitions for integer variables.
+  diskio.c   An example of glue function to attach existing disk I/O module to FatFs.
+  integer.h  Integer type definitions for FatFs.
   option     Optional external functions.
 
   Low level disk I/O module is not included in this archive because the FatFs
@@ -23,7 +24,7 @@ AGREEMENTS
  small embedded systems. This is a free software and is opened for education,
  research and commercial developments under license policy of following trems.
 
-  Copyright (C) 2011, ChaN, all right reserved.
+  Copyright (C) 2012, ChaN, all right reserved.
 
  * The FatFs module is a free software and there is NO WARRANTY.
  * No restriction on use. You can use, modify and redistribute it for
@@ -125,3 +126,10 @@ REVISION HISTORY
                        f_lseek() reports required table size on creating CLMP.
                        Extended format syntax of f_printf function.
                        Ignores duplicated directory separators in given path names.
+
+  Sep 06,'11 R0.09     f_mkfs() supports multiple partition to finish the multiple partition feature.
+                       Added f_fdisk(). (_MULTI_PARTITION = 2)
+
+  Aug 27,'12 R0.09a    Fixed assertion failure due to OS/2 EA on FAT12/16.
+                       Changed API rejects null object pointer to avoid crash.
+                       Changed option name _FS_SHARE to _FS_LOCK.
diff --git a/Projects/TempDataLogger/Lib/FATFs/diskio.c b/Projects/TempDataLogger/Lib/FATFs/diskio.c
index 400687734..085d5aec6 100644
--- a/Projects/TempDataLogger/Lib/FATFs/diskio.c
+++ b/Projects/TempDataLogger/Lib/FATFs/diskio.c
@@ -38,7 +38,7 @@ DRESULT disk_read (
 	BYTE drv,		/* Physical drive number (0..) */
 	BYTE *buff,		/* Data buffer to store read data */
 	DWORD sector,	/* Sector address (LBA) */
-	BYTE count		/* Number of sectors to read (1..255) */
+	BYTE count		/* Number of sectors to read (1..128) */
 )
 {
 	DataflashManager_ReadBlocks_RAM(sector, count, buff);
@@ -55,7 +55,7 @@ DRESULT disk_write (
 	BYTE drv,			/* Physical drive number (0..) */
 	const BYTE *buff,	/* Data to be written */
 	DWORD sector,		/* Sector address (LBA) */
-	BYTE count			/* Number of sectors to write (1..255) */
+	BYTE count			/* Number of sectors to write (1..128) */
 )
 {
 	DataflashManager_WriteBlocks_RAM(sector, count, buff);
diff --git a/Projects/TempDataLogger/Lib/FATFs/diskio.h b/Projects/TempDataLogger/Lib/FATFs/diskio.h
index 61d6601de..d3c3149a5 100644
--- a/Projects/TempDataLogger/Lib/FATFs/diskio.h
+++ b/Projects/TempDataLogger/Lib/FATFs/diskio.h
@@ -2,10 +2,12 @@
 /  Low level disk interface module include file
 /-----------------------------------------------------------------------*/
 
-#ifndef _DISKIO
+#ifndef _DISKIO_DEFINED
+#define _DISKIO_DEFINED
 
-#define _READONLY	0	/* 1: Read-only mode */
-#define _USE_IOCTL	1
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 #include "integer.h"
 
@@ -45,23 +47,9 @@ DRESULT disk_ioctl (BYTE, BYTE, void*);
 
 /* Generic command */
 #define CTRL_SYNC			0	/* Mandatory for write functions */
-#define GET_SECTOR_COUNT	1	/* Mandatory for only f_mkfs() */
-#define GET_SECTOR_SIZE		2	/* Mandatory for multiple sector size cfg */
-#define GET_BLOCK_SIZE		3	/* Mandatory for only f_mkfs() */
-#define CTRL_POWER			4
-#define CTRL_LOCK			5
-#define CTRL_EJECT			6
-/* MMC/SDC command */
-#define MMC_GET_TYPE		10
-#define MMC_GET_CSD			11
-#define MMC_GET_CID			12
-#define MMC_GET_OCR			13
-#define MMC_GET_SDSTAT		14
-/* ATA/CF command */
-#define ATA_GET_REV			20
-#define ATA_GET_MODEL		21
-#define ATA_GET_SN			22
-
-#define _DISKIO
+
+#ifdef __cplusplus
+}
 #endif
 
+#endif
diff --git a/Projects/TempDataLogger/Lib/FATFs/ff.c b/Projects/TempDataLogger/Lib/FATFs/ff.c
index 2e3d7a732..059b5885a 100644
--- a/Projects/TempDataLogger/Lib/FATFs/ff.c
+++ b/Projects/TempDataLogger/Lib/FATFs/ff.c
@@ -1,11 +1,11 @@
 /*----------------------------------------------------------------------------/
-/  FatFs - FAT file system module  R0.08b                 (C)ChaN, 2011
+/  FatFs - FAT file system module  R0.09a                 (C)ChaN, 2012
 /-----------------------------------------------------------------------------/
 / FatFs module is a generic FAT file system module for small embedded systems.
 / This is a free software that opened for education, research and commercial
 / developments under license policy of following terms.
 /
-/  Copyright (C) 2011, ChaN, all right reserved.
+/  Copyright (C) 2012, ChaN, all right reserved.
 /
 / * The FatFs module is a free software and there is NO WARRANTY.
 / * No restriction on use. You can use, modify and redistribute it for
@@ -86,7 +86,13 @@
 / Jan 15,'11 R0.08b Fast seek feature is also applied to f_read() and f_write().
 /                   f_lseek() reports required table size on creating CLMP.
 /                   Extended format syntax of f_printf function.
-/                   Ignores duplicated directory separators in given path names.
+/                   Ignores duplicated directory separators in given path name.
+/
+/ Sep 06,'11 R0.09  f_mkfs() supports multiple partition to finish the multiple partition feature.
+/                   Added f_fdisk(). (_MULTI_PARTITION = 2)
+/ Aug 27,'12 R0.09a Fixed assertion failure due to OS/2 EA on FAT12/16 volume.
+/                   Changed f_open() and f_opendir reject null object pointer to avoid crash.
+/                   Changed option name _FS_SHARE to _FS_LOCK.
 /---------------------------------------------------------------------------*/
 
 #include "ff.h"			/* FatFs configurations and declarations */
@@ -99,7 +105,7 @@
 
 ---------------------------------------------------------------------------*/
 
-#if _FATFS != 8237
+#if _FATFS != 4004	/* Revision ID */
 #error Wrong include file (ff.h).
 #endif
 
@@ -109,7 +115,7 @@
 #error Wrong sector size.
 #endif
 #if _MAX_SS != 512
-#define	SS(fs)	((fs)->ssize)	/* Multiple sector size */
+#define	SS(fs)	((fs)->ssize)	/* Variable sector size */
 #else
 #define	SS(fs)	512U			/* Fixed sector size */
 #endif
@@ -130,10 +136,10 @@
 #define	ABORT(fs, res)		{ fp->flag |= FA__ERROR; LEAVE_FF(fs, res); }
 
 
-/* File sharing feature */
-#if _FS_SHARE
+/* File access control feature */
+#if _FS_LOCK
 #if _FS_READONLY
-#error _FS_SHARE must be 0 on read-only cfg.
+#error _FS_LOCK must be 0 on read-only cfg.
 #endif
 typedef struct {
 	FATFS *fs;				/* File ID 1, volume (NULL:blank entry) */
@@ -144,10 +150,6 @@ typedef struct {
 #endif
 
 
-/* Misc definitions */
-#define LD_CLUST(dir)	(((DWORD)LD_WORD(dir+DIR_FstClusHI)<<16) | LD_WORD(dir+DIR_FstClusLO))
-#define ST_CLUST(dir,cl) {ST_WORD(dir+DIR_FstClusLO, cl); ST_WORD(dir+DIR_FstClusHI, (DWORD)cl>>16);}
-
 
 /* DBCS code ranges and SBCS extend char conversion table */
 
@@ -434,8 +436,10 @@ typedef struct {
 #define	DIR_Name			0	/* Short file name (11) */
 #define	DIR_Attr			11	/* Attribute (1) */
 #define	DIR_NTres			12	/* NT flag (1) */
+#define DIR_CrtTimeTenth	13	/* Created time sub-second (1) */
 #define	DIR_CrtTime			14	/* Created time (2) */
 #define	DIR_CrtDate			16	/* Created date (2) */
+#define DIR_LstAccDate		18	/* Last accessed date (2) */
 #define	DIR_FstClusHI		20	/* Higher 16-bit of first cluster (2) */
 #define	DIR_WrtTime			22	/* Modified time (2) */
 #define	DIR_WrtDate			24	/* Modified date (2) */
@@ -449,17 +453,22 @@ typedef struct {
 #define	SZ_DIR				32		/* Size of a directory entry */
 #define	LLE					0x40	/* Last long entry flag in LDIR_Ord */
 #define	DDE					0xE5	/* Deleted directory entry mark in DIR_Name[0] */
-#define	NDDE				0x05	/* Replacement of a character collides with DDE */
+#define	NDDE				0x05	/* Replacement of the character collides with DDE */
 
 
 /*------------------------------------------------------------*/
-/* Work area                                                  */
+/* Module private work area                                   */
+/*------------------------------------------------------------*/
+/* Note that uninitialized variables with static duration are
+/  zeroed/nulled at start-up. If not, the compiler or start-up
+/  routine is out of ANSI-C standard.
+*/
 
 #if _VOLUMES
 static
 FATFS *FatFs[_VOLUMES];	/* Pointer to the file system objects (logical drives) */
 #else
-#error Number of drives must not be 0.
+#error Number of volumes must not be 0.
 #endif
 
 static
@@ -470,28 +479,28 @@ static
 BYTE CurrVol;			/* Current drive */
 #endif
 
-#if _FS_SHARE
+#if _FS_LOCK
 static
-FILESEM	Files[_FS_SHARE];	/* File lock semaphores */
+FILESEM	Files[_FS_LOCK];	/* File lock semaphores */
 #endif
 
-#if _USE_LFN == 0			/* No LFN */
+#if _USE_LFN == 0			/* No LFN feature */
 #define	DEF_NAMEBUF			BYTE sfn[12]
 #define INIT_BUF(dobj)		(dobj).fn = sfn
 #define	FREE_BUF()
 
-#elif _USE_LFN == 1			/* LFN with static LFN working buffer */
+#elif _USE_LFN == 1			/* LFN feature with static working buffer */
 static WCHAR LfnBuf[_MAX_LFN+1];
 #define	DEF_NAMEBUF			BYTE sfn[12]
 #define INIT_BUF(dobj)		{ (dobj).fn = sfn; (dobj).lfn = LfnBuf; }
 #define	FREE_BUF()
 
-#elif _USE_LFN == 2 		/* LFN with dynamic LFN working buffer on the stack */
+#elif _USE_LFN == 2 		/* LFN feature with dynamic working buffer on the stack */
 #define	DEF_NAMEBUF			BYTE sfn[12]; WCHAR lbuf[_MAX_LFN+1]
 #define INIT_BUF(dobj)		{ (dobj).fn = sfn; (dobj).lfn = lbuf; }
 #define	FREE_BUF()
 
-#elif _USE_LFN == 3 		/* LFN with dynamic LFN working buffer on the heap */
+#elif _USE_LFN == 3 		/* LFN feature with dynamic working buffer on the heap */
 #define	DEF_NAMEBUF			BYTE sfn[12]; WCHAR *lfn
 #define INIT_BUF(dobj)		{ lfn = ff_memalloc((_MAX_LFN + 1) * 2); \
 							  if (!lfn) LEAVE_FF((dobj).fs, FR_NOT_ENOUGH_CORE); \
@@ -523,10 +532,10 @@ void mem_cpy (void* dst, const void* src, UINT cnt) {
 	const BYTE *s = (const BYTE*)src;
 
 #if _WORD_ACCESS == 1
-	while (cnt >= sizeof(int)) {
+	while (cnt >= sizeof (int)) {
 		*(int*)d = *(int*)s;
-		d += sizeof(int); s += sizeof(int);
-		cnt -= sizeof(int);
+		d += sizeof (int); s += sizeof (int);
+		cnt -= sizeof (int);
 	}
 #endif
 	while (cnt--)
@@ -581,7 +590,8 @@ void unlock_fs (
 	FRESULT res		/* Result code to be returned */
 )
 {
-	if (res != FR_NOT_ENABLED &&
+	if (fs &&
+		res != FR_NOT_ENABLED &&
 		res != FR_INVALID_DRIVE &&
 		res != FR_INVALID_OBJECT &&
 		res != FR_TIMEOUT) {
@@ -593,9 +603,9 @@ void unlock_fs (
 
 
 /*-----------------------------------------------------------------------*/
-/* File shareing control functions                                       */
+/* File lock control functions                                           */
 /*-----------------------------------------------------------------------*/
-#if _FS_SHARE
+#if _FS_LOCK
 
 static
 FRESULT chk_lock (	/* Check if the file can be accessed */
@@ -606,7 +616,7 @@ FRESULT chk_lock (	/* Check if the file can be accessed */
 	UINT i, be;
 
 	/* Search file semaphore table */
-	for (i = be = 0; i < _FS_SHARE; i++) {
+	for (i = be = 0; i < _FS_LOCK; i++) {
 		if (Files[i].fs) {	/* Existing entry */
 			if (Files[i].fs == dj->fs &&	 	/* Check if the file matched with an open file */
 				Files[i].clu == dj->sclust &&
@@ -615,7 +625,7 @@ FRESULT chk_lock (	/* Check if the file can be accessed */
 			be++;
 		}
 	}
-	if (i == _FS_SHARE)	/* The file is not opened */
+	if (i == _FS_LOCK)	/* The file is not opened */
 		return (be || acc == 2) ? FR_OK : FR_TOO_MANY_OPEN_FILES;	/* Is there a blank entry for new file? */
 
 	/* The file has been opened. Reject any open against writing file and all write mode open */
@@ -624,14 +634,12 @@ FRESULT chk_lock (	/* Check if the file can be accessed */
 
 
 static
-int enq_lock (	/* Check if an entry is available for a new file */
-	FATFS* fs	/* File system object */
-)
+int enq_lock (void)	/* Check if an entry is available for a new file */
 {
 	UINT i;
 
-	for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ;
-	return (i == _FS_SHARE) ? 0 : 1;
+	for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ;
+	return (i == _FS_LOCK) ? 0 : 1;
 }
 
 
@@ -644,15 +652,15 @@ UINT inc_lock (	/* Increment file open counter and returns its index (0:int erro
 	UINT i;
 
 
-	for (i = 0; i < _FS_SHARE; i++) {	/* Find the file */
+	for (i = 0; i < _FS_LOCK; i++) {	/* Find the file */
 		if (Files[i].fs == dj->fs &&
 			Files[i].clu == dj->sclust &&
 			Files[i].idx == dj->index) break;
 	}
 
-	if (i == _FS_SHARE) {				/* Not opened. Register it as new. */
-		for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ;
-		if (i == _FS_SHARE) return 0;	/* No space to register (int err) */
+	if (i == _FS_LOCK) {				/* Not opened. Register it as new. */
+		for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ;
+		if (i == _FS_LOCK) return 0;	/* No space to register (int err) */
 		Files[i].fs = dj->fs;
 		Files[i].clu = dj->sclust;
 		Files[i].idx = dj->index;
@@ -676,7 +684,7 @@ FRESULT dec_lock (	/* Decrement file open counter */
 	FRESULT res;
 
 
-	if (--i < _FS_SHARE) {
+	if (--i < _FS_LOCK) {
 		n = Files[i].ctr;
 		if (n == 0x100) n = 0;
 		if (n) n--;
@@ -697,7 +705,7 @@ void clear_lock (	/* Clear lock entries of the volume */
 {
 	UINT i;
 
-	for (i = 0; i < _FS_SHARE; i++) {
+	for (i = 0; i < _FS_LOCK; i++) {
 		if (Files[i].fs == fs) Files[i].fs = 0;
 	}
 }
@@ -776,7 +784,7 @@ FRESULT sync (	/* FR_OK: successful, FR_DISK_ERR: failed */
 			fs->fsi_flag = 0;
 		}
 		/* Make sure that no pending write process in the physical drive */
-		if (disk_ioctl(fs->drv, CTRL_SYNC, (void*)0) != RES_OK)
+		if (disk_ioctl(fs->drv, CTRL_SYNC, 0) != RES_OK)
 			res = FR_DISK_ERR;
 	}
 
@@ -819,7 +827,7 @@ DWORD get_fat (	/* 0xFFFFFFFF:Disk error, 1:Internal error, Else:Cluster status
 	BYTE *p;
 
 
-	if (clst < 2 || clst >= fs->n_fatent)	/* Chack range */
+	if (clst < 2 || clst >= fs->n_fatent)	/* Check range */
 		return 1;
 
 	switch (fs->fs_type) {
@@ -870,7 +878,7 @@ FRESULT put_fat (
 	} else {
 		switch (fs->fs_type) {
 		case FS_FAT12 :
-			bc = clst; bc += bc / 2;
+			bc = (UINT)clst; bc += bc / 2;
 			res = move_window(fs, fs->fatbase + (bc / SS(fs)));
 			if (res != FR_OK) break;
 			p = &fs->win[bc % SS(fs)];
@@ -924,7 +932,7 @@ FRESULT remove_chain (
 	FRESULT res;
 	DWORD nxt;
 #if _USE_ERASE
-	DWORD scl = clst, ecl = clst, resion[2];
+	DWORD scl = clst, ecl = clst, rt[2];
 #endif
 
 	if (clst < 2 || clst >= fs->n_fatent) {	/* Check range */
@@ -944,12 +952,12 @@ FRESULT remove_chain (
 				fs->fsi_flag = 1;
 			}
 #if _USE_ERASE
-			if (ecl + 1 == nxt) {	/* Next cluster is contiguous */
+			if (ecl + 1 == nxt) {	/* Is next cluster contiguous? */
 				ecl = nxt;
-			} else {				/* End of contiguous clusters */
-				resion[0] = clust2sect(fs, scl);					/* Start sector */
-				resion[1] = clust2sect(fs, ecl) + fs->csize - 1;	/* End sector */
-				disk_ioctl(fs->drv, CTRL_ERASE_SECTOR, resion);		/* Erase the block */
+			} else {				/* End of contiguous clusters */ 
+				rt[0] = clust2sect(fs, scl);					/* Start sector */
+				rt[1] = clust2sect(fs, ecl) + fs->csize - 1;	/* End sector */
+				disk_ioctl(fs->drv, CTRL_ERASE_SECTOR, rt);		/* Erase the block */
 				scl = ecl = nxt;
 			}
 #endif
@@ -1058,7 +1066,7 @@ DWORD clmt_clust (	/* <2:Error, >=2:Cluster number */
 static
 FRESULT dir_sdi (
 	DIR *dj,		/* Pointer to directory object */
-	WORD idx		/* Directory index number */
+	WORD idx		/* Index of directory table */
 )
 {
 	DWORD clst;
@@ -1100,7 +1108,7 @@ FRESULT dir_sdi (
 
 
 /*-----------------------------------------------------------------------*/
-/* Directory handling - Move directory index next                        */
+/* Directory handling - Move directory table index next                  */
 /*-----------------------------------------------------------------------*/
 
 static
@@ -1113,6 +1121,7 @@ FRESULT dir_next (	/* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT an
 	WORD i;
 
 
+	stretch = stretch;		/* To suppress warning on read-only cfg. */
 	i = dj->index + 1;
 	if (!i || !dj->sect)	/* Report EOT when index has reached 65535 */
 		return FR_NO_FILE;
@@ -1166,6 +1175,40 @@ FRESULT dir_next (	/* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT an
 
 
 
+/*-----------------------------------------------------------------------*/
+/* Directory handling - Load/Store start cluster number                  */
+/*-----------------------------------------------------------------------*/
+
+static
+DWORD ld_clust (
+	FATFS *fs,	/* Pointer to the fs object */
+	BYTE *dir	/* Pointer to the directory entry */
+)
+{
+	DWORD cl;
+
+	cl = LD_WORD(dir+DIR_FstClusLO);
+	if (fs->fs_type == FS_FAT32)
+		cl |= (DWORD)LD_WORD(dir+DIR_FstClusHI) << 16;
+
+	return cl;
+}
+
+
+#if !_FS_READONLY
+static
+void st_clust (
+	BYTE *dir,	/* Pointer to the directory entry */
+	DWORD cl	/* Value to be set */
+)
+{
+	ST_WORD(dir+DIR_FstClusLO, cl);
+	ST_WORD(dir+DIR_FstClusHI, cl >> 16);
+}
+#endif
+
+
+
 /*-----------------------------------------------------------------------*/
 /* LFN handling - Test/Pick/Fit an LFN segment from/to directory entry   */
 /*-----------------------------------------------------------------------*/
@@ -1777,7 +1820,7 @@ FRESULT create_name (
 		if (c >= 0x80) {				/* Extended char? */
 			b |= 3;						/* Eliminate NT flag */
 #ifdef _EXCVT
-			c = excvt[c-0x80];			/* Upper conversion (SBCS) */
+			c = excvt[c - 0x80];		/* Upper conversion (SBCS) */
 #else
 #if !_DF1S	/* ASCII only cfg */
 			return FR_INVALID_NAME;
@@ -1933,7 +1976,6 @@ FRESULT follow_path (	/* FR_OK(0): successful, !=0: error code */
 	if ((UINT)*path < ' ') {			/* Nul path means the start directory itself */
 		res = dir_sdi(dj, 0);
 		dj->dir = 0;
-
 	} else {							/* Follow path */
 		for (;;) {
 			res = create_name(dj, &path);	/* Get a segment */
@@ -1941,7 +1983,7 @@ FRESULT follow_path (	/* FR_OK(0): successful, !=0: error code */
 			res = dir_find(dj);				/* Find it */
 			ns = *(dj->fn+NS);
 			if (res != FR_OK) {				/* Failed to find the object */
-				if (res != FR_NO_FILE) break;	/* Abort if any hard error occured */
+				if (res != FR_NO_FILE) break;	/* Abort if any hard error occurred */
 				/* Object not found */
 				if (_FS_RPATH && (ns & NS_DOT)) {	/* If dot entry is not exit */
 					dj->sclust = 0; dj->dir = 0;	/* It is the root dir */
@@ -1957,7 +1999,7 @@ FRESULT follow_path (	/* FR_OK(0): successful, !=0: error code */
 			if (!(dir[DIR_Attr] & AM_DIR)) {	/* Cannot follow because it is a file */
 				res = FR_NO_PATH; break;
 			}
-			dj->sclust = LD_CLUST(dir);
+			dj->sclust = ld_clust(dj->fs, dir);
 		}
 	}
 
@@ -1968,11 +2010,11 @@ FRESULT follow_path (	/* FR_OK(0): successful, !=0: error code */
 
 
 /*-----------------------------------------------------------------------*/
-/* Load boot record and check if it is an FAT boot record                */
+/* Load a sector and check if it is an FAT Volume Boot Record            */
 /*-----------------------------------------------------------------------*/
 
 static
-BYTE check_fs (	/* 0:The FAT BR, 1:Valid BR but not an FAT, 2:Not a BR, 3:Disk error */
+BYTE check_fs (	/* 0:FAT-VBR, 1:Any BR but not FAT, 2:Not a BR, 3:Disk error */
 	FATFS *fs,	/* File system object */
 	DWORD sect	/* Sector# (lba) to check if it is an FAT boot record or not */
 )
@@ -2001,10 +2043,10 @@ static
 FRESULT chk_mounted (	/* FR_OK(0): successful, !=0: any error occurred */
 	const TCHAR **path,	/* Pointer to pointer to the path name (drive number) */
 	FATFS **rfs,		/* Pointer to pointer to the found file system object */
-	BYTE chk_wp			/* !=0: Check media write protection for write access */
+	BYTE wmode			/* !=0: Check write protection for write access */
 )
 {
-	BYTE fmt, b, *tbl;
+	BYTE fmt, b, pi, *tbl;
 	UINT vol;
 	DSTATUS stat;
 	DWORD bsect, fasize, tsect, sysect, nclst, szbfat;
@@ -2012,6 +2054,7 @@ FRESULT chk_mounted (	/* FR_OK(0): successful, !=0: any error occurred */
 	const TCHAR *p = *path;
 	FATFS *fs;
 
+
 	/* Get logical drive number from the path name */
 	vol = p[0] - '0';					/* Is there a drive number? */
 	if (vol <= 9 && p[1] == ':') {		/* Found a drive number, get and strip it */
@@ -2024,55 +2067,56 @@ FRESULT chk_mounted (	/* FR_OK(0): successful, !=0: any error occurred */
 #endif
 	}
 
-	/* Check if the logical drive is valid or not */
+	/* Check if the file system object is valid or not */
+	*rfs = 0;
 	if (vol >= _VOLUMES) 				/* Is the drive number valid? */
 		return FR_INVALID_DRIVE;
-	*rfs = fs = FatFs[vol];				/* Return pointer to the corresponding file system object */
+	fs = FatFs[vol];					/* Get corresponding file system object */
 	if (!fs) return FR_NOT_ENABLED;		/* Is the file system object available? */
 
 	ENTER_FF(fs);						/* Lock file system */
 
-	if (fs->fs_type) {					/* If the logical drive has been mounted */
+	*rfs = fs;							/* Return pointer to the corresponding file system object */
+	if (fs->fs_type) {					/* If the volume has been mounted */
 		stat = disk_status(fs->drv);
 		if (!(stat & STA_NOINIT)) {		/* and the physical drive is kept initialized (has not been changed), */
-#if !_FS_READONLY
-			if (chk_wp && (stat & STA_PROTECT))	/* Check write protection if needed */
+			if (!_FS_READONLY && wmode && (stat & STA_PROTECT))	/* Check write protection if needed */
 				return FR_WRITE_PROTECTED;
-#endif
 			return FR_OK;				/* The file system object is valid */
 		}
 	}
 
-	/* The logical drive must be mounted. */
-	/* Following code attempts to mount a volume. (analyze BPB and initialize the fs object) */
+	/* The file system object is not valid. */
+	/* Following code attempts to mount the volume. (analyze BPB and initialize the fs object) */
 
 	fs->fs_type = 0;					/* Clear the file system object */
-	fs->drv = (BYTE)LD2PD(vol);			/* Bind the logical drive and a physical drive */
-	stat = disk_initialize(fs->drv);	/* Initialize low level disk I/O layer */
+	fs->drv = LD2PD(vol);				/* Bind the logical drive and a physical drive */
+	stat = disk_initialize(fs->drv);	/* Initialize the physical drive */
 	if (stat & STA_NOINIT)				/* Check if the initialization succeeded */
-		return FR_NOT_READY;			/* Failed to initialize due to no media or hard error */
+		return FR_NOT_READY;			/* Failed to initialize due to no medium or hard error */
+	if (!_FS_READONLY && wmode && (stat & STA_PROTECT))	/* Check disk write protection if needed */
+		return FR_WRITE_PROTECTED;
 #if _MAX_SS != 512						/* Get disk sector size (variable sector size cfg only) */
 	if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &fs->ssize) != RES_OK)
 		return FR_DISK_ERR;
 #endif
-#if !_FS_READONLY
-	if (chk_wp && (stat & STA_PROTECT))	/* Check disk write protection if needed */
-		return FR_WRITE_PROTECTED;
-#endif
-	/* Search FAT partition on the drive. Supports only generic partitioning, FDISK and SFD. */
-	fmt = check_fs(fs, bsect = 0);		/* Check sector 0 if it is a VBR */
-	if (fmt == 1) {						/* Not an FAT-VBR, the disk may be partitioned */
-		/* Check the partition listed in top of the partition table */
-		tbl = &fs->win[MBR_Table + LD2PT(vol) * SZ_PTE];/* Partition table */
-		if (tbl[4]) {									/* Is the partition existing? */
-			bsect = LD_DWORD(&tbl[8]);					/* Partition offset in LBA */
-			fmt = check_fs(fs, bsect);					/* Check the partition */
+	/* Search FAT partition on the drive. Supports only generic partitions, FDISK and SFD. */
+	fmt = check_fs(fs, bsect = 0);		/* Load sector 0 and check if it is an FAT-VBR (in SFD) */
+	if (LD2PT(vol) && !fmt) fmt = 1;	/* Force non-SFD if the volume is forced partition */
+	if (fmt == 1) {						/* Not an FAT-VBR, the physical drive can be partitioned */
+		/* Check the partition listed in the partition table */
+		pi = LD2PT(vol);
+		if (pi) pi--;
+		tbl = &fs->win[MBR_Table + pi * SZ_PTE];/* Partition table */
+		if (tbl[4]) {						/* Is the partition existing? */
+			bsect = LD_DWORD(&tbl[8]);		/* Partition offset in LBA */
+			fmt = check_fs(fs, bsect);		/* Check the partition */
 		}
 	}
 	if (fmt == 3) return FR_DISK_ERR;
-	if (fmt) return FR_NO_FILESYSTEM;					/* No FAT volume is found */
+	if (fmt) return FR_NO_FILESYSTEM;		/* No FAT volume is found */
 
-	/* Following code initializes the file system object */
+	/* An FAT volume is found. Following code initializes the file system object */
 
 	if (LD_WORD(fs->win+BPB_BytsPerSec) != SS(fs))		/* (BPB_BytsPerSec must be equal to the physical sector size) */
 		return FR_NO_FILESYSTEM;
@@ -2148,7 +2192,7 @@ FRESULT chk_mounted (	/* FR_OK(0): successful, !=0: any error occurred */
 #if _FS_RPATH
 	fs->cdir = 0;			/* Current directory (root dir) */
 #endif
-#if _FS_SHARE				/* Clear file lock semaphores */
+#if _FS_LOCK				/* Clear file lock semaphores */
 	clear_lock(fs);
 #endif
 
@@ -2164,16 +2208,19 @@ FRESULT chk_mounted (	/* FR_OK(0): successful, !=0: any error occurred */
 
 static
 FRESULT validate (	/* FR_OK(0): The object is valid, !=0: Invalid */
-	FATFS *fs,		/* Pointer to the file system object */
-	WORD id			/* Member id of the target object to be checked */
+	void* obj		/* Pointer to the object FIL/DIR to check validity */
 )
 {
-	if (!fs || !fs->fs_type || fs->id != id)
+	FIL *fil;
+
+
+	fil = (FIL*)obj;	/* Assuming offset of fs and id in the FIL/DIR is identical */
+	if (!fil->fs || !fil->fs->fs_type || fil->fs->id != fil->id)
 		return FR_INVALID_OBJECT;
 
-	ENTER_FF(fs);		/* Lock file system */
+	ENTER_FF(fil->fs);		/* Lock file system */
 
-	if (disk_status(fs->drv) & STA_NOINIT)
+	if (disk_status(fil->fs->drv) & STA_NOINIT)
 		return FR_NOT_READY;
 
 	return FR_OK;
@@ -2202,27 +2249,27 @@ FRESULT f_mount (
 	FATFS *rfs;
 
 
-	if (vol >= _VOLUMES)			/* Check if the drive number is valid */
+	if (vol >= _VOLUMES)		/* Check if the drive number is valid */
 		return FR_INVALID_DRIVE;
-	rfs = FatFs[vol];				/* Get current fs object */
+	rfs = FatFs[vol];			/* Get current fs object */
 
 	if (rfs) {
-#if _FS_SHARE
+#if _FS_LOCK
 		clear_lock(rfs);
 #endif
-#if _FS_REENTRANT					/* Discard sync object of the current volume */
+#if _FS_REENTRANT				/* Discard sync object of the current volume */
 		if (!ff_del_syncobj(rfs->sobj)) return FR_INT_ERR;
 #endif
-		rfs->fs_type = 0;			/* Clear old fs object */
+		rfs->fs_type = 0;		/* Clear old fs object */
 	}
 
 	if (fs) {
-		fs->fs_type = 0;			/* Clear new fs object */
-#if _FS_REENTRANT					/* Create sync object for the new volume */
+		fs->fs_type = 0;		/* Clear new fs object */
+#if _FS_REENTRANT				/* Create sync object for the new volume */
 		if (!ff_cre_syncobj(vol, &fs->sobj)) return FR_INT_ERR;
 #endif
 	}
-	FatFs[vol] = fs;				/* Register new fs object */
+	FatFs[vol] = fs;			/* Register new fs object */
 
 	return FR_OK;
 }
@@ -2246,6 +2293,7 @@ FRESULT f_open (
 	DEF_NAMEBUF;
 
 
+	if (!fp) return FR_INVALID_OBJECT;
 	fp->fs = 0;			/* Clear file object */
 
 #if !_FS_READONLY
@@ -2255,103 +2303,104 @@ FRESULT f_open (
 	mode &= FA_READ;
 	res = chk_mounted(&path, &dj.fs, 0);
 #endif
-	INIT_BUF(dj);
-	if (res == FR_OK)
+	if (res == FR_OK) {
+		INIT_BUF(dj);
 		res = follow_path(&dj, path);	/* Follow the file path */
-	dir = dj.dir;
-
+		dir = dj.dir;
 #if !_FS_READONLY	/* R/W configuration */
-	if (res == FR_OK) {
-		if (!dir)	/* Current dir itself */
-			res = FR_INVALID_NAME;
-#if _FS_SHARE
-		else
-			res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
+		if (res == FR_OK) {
+			if (!dir)	/* Current dir itself */
+				res = FR_INVALID_NAME;
+#if _FS_LOCK
+			else
+				res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
 #endif
-	}
-	/* Create or Open a file */
-	if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) {
-		DWORD dw, cl;
-
-		if (res != FR_OK) {					/* No file, create new */
-			if (res == FR_NO_FILE)			/* There is no file to open, create a new entry */
-#if _FS_SHARE
-				res = enq_lock(dj.fs) ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES;
+		}
+		/* Create or Open a file */
+		if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) {
+			DWORD dw, cl;
+
+			if (res != FR_OK) {					/* No file, create new */
+				if (res == FR_NO_FILE)			/* There is no file to open, create a new entry */
+#if _FS_LOCK
+					res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES;
 #else
-				res = dir_register(&dj);
+					res = dir_register(&dj);
 #endif
-			mode |= FA_CREATE_ALWAYS;		/* File is created */
-			dir = dj.dir;					/* New entry */
-		}
-		else {								/* Any object is already existing */
-			if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) {	/* Cannot overwrite it (R/O or DIR) */
-				res = FR_DENIED;
-			} else {
-				if (mode & FA_CREATE_NEW)	/* Cannot create as new file */
-					res = FR_EXIST;
+				mode |= FA_CREATE_ALWAYS;		/* File is created */
+				dir = dj.dir;					/* New entry */
 			}
-		}
-		if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) {	/* Truncate it if overwrite mode */
-			dw = get_fattime();					/* Created time */
-			ST_DWORD(dir+DIR_CrtTime, dw);
-			dir[DIR_Attr] = 0;					/* Reset attribute */
-			ST_DWORD(dir+DIR_FileSize, 0);		/* size = 0 */
-			cl = LD_CLUST(dir);					/* Get start cluster */
-			ST_CLUST(dir, 0);					/* cluster = 0 */
-			dj.fs->wflag = 1;
-			if (cl) {							/* Remove the cluster chain if exist */
-				dw = dj.fs->winsect;
-				res = remove_chain(dj.fs, cl);
-				if (res == FR_OK) {
-					dj.fs->last_clust = cl - 1;	/* Reuse the cluster hole */
-					res = move_window(dj.fs, dw);
+			else {								/* Any object is already existing */
+				if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) {	/* Cannot overwrite it (R/O or DIR) */
+					res = FR_DENIED;
+				} else {
+					if (mode & FA_CREATE_NEW)	/* Cannot create as new file */
+						res = FR_EXIST;
+				}
+			}
+			if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) {	/* Truncate it if overwrite mode */
+				dw = get_fattime();					/* Created time */
+				ST_DWORD(dir+DIR_CrtTime, dw);
+				dir[DIR_Attr] = 0;					/* Reset attribute */
+				ST_DWORD(dir+DIR_FileSize, 0);		/* size = 0 */
+				cl = ld_clust(dj.fs, dir);			/* Get start cluster */
+				st_clust(dir, 0);					/* cluster = 0 */
+				dj.fs->wflag = 1;
+				if (cl) {							/* Remove the cluster chain if exist */
+					dw = dj.fs->winsect;
+					res = remove_chain(dj.fs, cl);
+					if (res == FR_OK) {
+						dj.fs->last_clust = cl - 1;	/* Reuse the cluster hole */
+						res = move_window(dj.fs, dw);
+					}
 				}
 			}
 		}
-	}
-	else {	/* Open an existing file */
-		if (res == FR_OK) {						/* Follow succeeded */
-			if (dir[DIR_Attr] & AM_DIR) {		/* It is a directory */
-				res = FR_NO_FILE;
-			} else {
-				if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */
-					res = FR_DENIED;
+		else {	/* Open an existing file */
+			if (res == FR_OK) {						/* Follow succeeded */
+				if (dir[DIR_Attr] & AM_DIR) {		/* It is a directory */
+					res = FR_NO_FILE;
+				} else {
+					if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */
+						res = FR_DENIED;
+				}
 			}
 		}
-	}
-	if (res == FR_OK) {
-		if (mode & FA_CREATE_ALWAYS)			/* Set file change flag if created or overwritten */
-			mode |= FA__WRITTEN;
-		fp->dir_sect = dj.fs->winsect;			/* Pointer to the directory entry */
-		fp->dir_ptr = dir;
-#if _FS_SHARE
-		fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
-		if (!fp->lockid) res = FR_INT_ERR;
+		if (res == FR_OK) {
+			if (mode & FA_CREATE_ALWAYS)			/* Set file change flag if created or overwritten */
+				mode |= FA__WRITTEN;
+			fp->dir_sect = dj.fs->winsect;			/* Pointer to the directory entry */
+			fp->dir_ptr = dir;
+#if _FS_LOCK
+			fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
+			if (!fp->lockid) res = FR_INT_ERR;
 #endif
-	}
+		}
 
 #else				/* R/O configuration */
-	if (res == FR_OK) {					/* Follow succeeded */
-		if (!dir) {						/* Current dir itself */
-			res = FR_INVALID_NAME;
-		} else {
-			if (dir[DIR_Attr] & AM_DIR)	/* It is a directory */
-				res = FR_NO_FILE;
+		if (res == FR_OK) {					/* Follow succeeded */
+			dir = dj.dir;
+			if (!dir) {						/* Current dir itself */
+				res = FR_INVALID_NAME;
+			} else {
+				if (dir[DIR_Attr] & AM_DIR)	/* It is a directory */
+					res = FR_NO_FILE;
+			}
 		}
-	}
 #endif
-	FREE_BUF();
+		FREE_BUF();
 
-	if (res == FR_OK) {
-		fp->flag = mode;					/* File access mode */
-		fp->sclust = LD_CLUST(dir);			/* File start cluster */
-		fp->fsize = LD_DWORD(dir+DIR_FileSize);	/* File size */
-		fp->fptr = 0;						/* File pointer */
-		fp->dsect = 0;
+		if (res == FR_OK) {
+			fp->flag = mode;					/* File access mode */
+			fp->sclust = ld_clust(dj.fs, dir);	/* File start cluster */
+			fp->fsize = LD_DWORD(dir+DIR_FileSize);	/* File size */
+			fp->fptr = 0;						/* File pointer */
+			fp->dsect = 0;
 #if _USE_FASTSEEK
-		fp->cltbl = 0;						/* Normal seek mode */
+			fp->cltbl = 0;						/* Normal seek mode */
 #endif
-		fp->fs = dj.fs; fp->id = dj.fs->id;	/* Validate file object */
+			fp->fs = dj.fs; fp->id = dj.fs->id;	/* Validate file object */
+		}
 	}
 
 	LEAVE_FF(dj.fs, res);
@@ -2377,9 +2426,9 @@ FRESULT f_read (
 	BYTE csect, *rbuff = buff;
 
 
-	*br = 0;	/* Initialize byte counter */
+	*br = 0;	/* Clear read byte counter */
 
-	res = validate(fp->fs, fp->id);				/* Check validity */
+	res = validate(fp);							/* Check validity */
 	if (res != FR_OK) LEAVE_FF(fp->fs, res);
 	if (fp->flag & FA__ERROR)					/* Aborted file? */
 		LEAVE_FF(fp->fs, FR_INT_ERR);
@@ -2443,7 +2492,7 @@ FRESULT f_read (
 #endif
 			fp->dsect = sect;
 		}
-		rcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs));	/* Get partial sector data from sector buffer */
+		rcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs));	/* Get partial sector data from sector buffer */
 		if (rcnt > btr) rcnt = btr;
 #if _FS_TINY
 		if (move_window(fp->fs, fp->dsect))		/* Move sector window */
@@ -2479,9 +2528,9 @@ FRESULT f_write (
 	BYTE csect;
 
 
-	*bw = 0;	/* Initialize byte counter */
+	*bw = 0;	/* Clear write byte counter */
 
-	res = validate(fp->fs, fp->id);			/* Check validity */
+	res = validate(fp);						/* Check validity */
 	if (res != FR_OK) LEAVE_FF(fp->fs, res);
 	if (fp->flag & FA__ERROR)				/* Aborted file? */
 		LEAVE_FF(fp->fs, FR_INT_ERR);
@@ -2558,7 +2607,7 @@ FRESULT f_write (
 #endif
 			fp->dsect = sect;
 		}
-		wcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */
+		wcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */
 		if (wcnt > btw) wcnt = btw;
 #if _FS_TINY
 		if (move_window(fp->fs, fp->dsect))	/* Move sector window */
@@ -2593,7 +2642,7 @@ FRESULT f_sync (
 	BYTE *dir;
 
 
-	res = validate(fp->fs, fp->id);		/* Check validity of the object */
+	res = validate(fp);					/* Check validity of the object */
 	if (res == FR_OK) {
 		if (fp->flag & FA__WRITTEN) {	/* Has the file been written? */
 #if !_FS_TINY	/* Write-back dirty buffer */
@@ -2609,9 +2658,10 @@ FRESULT f_sync (
 				dir = fp->dir_ptr;
 				dir[DIR_Attr] |= AM_ARC;					/* Set archive bit */
 				ST_DWORD(dir+DIR_FileSize, fp->fsize);		/* Update file size */
-				ST_CLUST(dir, fp->sclust);					/* Update start cluster */
+				st_clust(dir, fp->sclust);					/* Update start cluster */
 				tim = get_fattime();						/* Update updated time */
 				ST_DWORD(dir+DIR_WrtTime, tim);
+				ST_WORD(dir+DIR_LstAccDate, 0);
 				fp->flag &= ~FA__WRITTEN;
 				fp->fs->wflag = 1;
 				res = sync(fp->fs);
@@ -2637,21 +2687,26 @@ FRESULT f_close (
 {
 	FRESULT res;
 
-#if _FS_READONLY
-	FATFS *fs = fp->fs;
-	res = validate(fs, fp->id);
-	if (res == FR_OK) fp->fs = 0;	/* Discard file object */
-	LEAVE_FF(fs, res);
 
+#if _FS_READONLY
+	res = validate(fp);
+	{
+#if _FS_REENTRANT
+		FATFS *fs = fp->fs;
+#endif
+		if (res == FR_OK) fp->fs = 0;	/* Discard file object */
+		LEAVE_FF(fs, res);
+	}
 #else
 	res = f_sync(fp);		/* Flush cached data */
-#if _FS_SHARE
+#if _FS_LOCK
 	if (res == FR_OK) {		/* Decrement open counter */
 #if _FS_REENTRANT
-		res = validate(fp->fs, fp->id);
+		FATFS *fs = fp->fs;;
+		res = validate(fp);
 		if (res == FR_OK) {
-			res = dec_lock(fp->lockid);
-			unlock_fs(fp->fs, FR_OK);
+			res = dec_lock(fp->lockid);	
+			unlock_fs(fs, FR_OK);
 		}
 #else
 		res = dec_lock(fp->lockid);
@@ -2704,7 +2759,7 @@ FRESULT f_chdir (
 				dj.fs->cdir = dj.sclust;	/* Start directory itself */
 			} else {
 				if (dj.dir[DIR_Attr] & AM_DIR)	/* Reached to the directory */
-					dj.fs->cdir = LD_CLUST(dj.dir);
+					dj.fs->cdir = ld_clust(dj.fs, dj.dir);
 				else
 					res = FR_NO_PATH;		/* Reached but a file */
 			}
@@ -2742,14 +2797,14 @@ FRESULT f_getcwd (
 			if (res != FR_OK) break;
 			res = dir_read(&dj);
 			if (res != FR_OK) break;
-			dj.sclust = LD_CLUST(dj.dir);	/* Goto parent dir */
+			dj.sclust = ld_clust(dj.fs, dj.dir);	/* Goto parent dir */
 			res = dir_sdi(&dj, 0);
 			if (res != FR_OK) break;
 			do {							/* Find the entry links to the child dir */
 				res = dir_read(&dj);
 				if (res != FR_OK) break;
-				if (ccl == LD_CLUST(dj.dir)) break;	/* Found the entry */
-				res = dir_next(&dj, 0);
+				if (ccl == ld_clust(dj.fs, dj.dir)) break;	/* Found the entry */
+				res = dir_next(&dj, 0);	
 			} while (res == FR_OK);
 			if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */
 			if (res != FR_OK) break;
@@ -2803,7 +2858,7 @@ FRESULT f_lseek (
 	FRESULT res;
 
 
-	res = validate(fp->fs, fp->id);		/* Check validity of the object */
+	res = validate(fp);					/* Check validity of the object */
 	if (res != FR_OK) LEAVE_FF(fp->fs, res);
 	if (fp->flag & FA__ERROR)			/* Check abort flag */
 		LEAVE_FF(fp->fs, FR_INT_ERR);
@@ -2959,10 +3014,14 @@ FRESULT f_opendir (
 )
 {
 	FRESULT res;
+	FATFS *fs;
 	DEF_NAMEBUF;
 
 
+	if (!dj) return FR_INVALID_OBJECT;
+
 	res = chk_mounted(&path, &dj->fs, 0);
+	fs = dj->fs;
 	if (res == FR_OK) {
 		INIT_BUF(*dj);
 		res = follow_path(dj, path);			/* Follow the path to the directory */
@@ -2970,20 +3029,23 @@ FRESULT f_opendir (
 		if (res == FR_OK) {						/* Follow completed */
 			if (dj->dir) {						/* It is not the root dir */
 				if (dj->dir[DIR_Attr] & AM_DIR) {	/* The object is a directory */
-					dj->sclust = LD_CLUST(dj->dir);
+					dj->sclust = ld_clust(fs, dj->dir);
 				} else {						/* The object is not a directory */
 					res = FR_NO_PATH;
 				}
 			}
 			if (res == FR_OK) {
-				dj->id = dj->fs->id;
+				dj->id = fs->id;
 				res = dir_sdi(dj, 0);			/* Rewind dir */
 			}
 		}
 		if (res == FR_NO_FILE) res = FR_NO_PATH;
+		if (res != FR_OK) dj->fs = 0;			/* Invalidate the dir object if function faild */
+	} else {
+		dj->fs = 0;
 	}
 
-	LEAVE_FF(dj->fs, res);
+	LEAVE_FF(fs, res);
 }
 
 
@@ -3002,7 +3064,7 @@ FRESULT f_readdir (
 	DEF_NAMEBUF;
 
 
-	res = validate(dj->fs, dj->id);			/* Check validity of the object */
+	res = validate(dj);						/* Check validity of the object */
 	if (res == FR_OK) {
 		if (!fno) {
 			res = dir_sdi(dj, 0);			/* Rewind the directory object */
@@ -3075,6 +3137,7 @@ FRESULT f_getfree (
 )
 {
 	FRESULT res;
+	FATFS *fs;
 	DWORD n, clst, sect, stat;
 	UINT i;
 	BYTE fat, *p;
@@ -3082,32 +3145,33 @@ FRESULT f_getfree (
 
 	/* Get drive number */
 	res = chk_mounted(&path, fatfs, 0);
+	fs = *fatfs;
 	if (res == FR_OK) {
 		/* If free_clust is valid, return it without full cluster scan */
-		if ((*fatfs)->free_clust <= (*fatfs)->n_fatent - 2) {
-			*nclst = (*fatfs)->free_clust;
+		if (fs->free_clust <= fs->n_fatent - 2) {
+			*nclst = fs->free_clust;
 		} else {
 			/* Get number of free clusters */
-			fat = (*fatfs)->fs_type;
+			fat = fs->fs_type;
 			n = 0;
 			if (fat == FS_FAT12) {
 				clst = 2;
 				do {
-					stat = get_fat(*fatfs, clst);
+					stat = get_fat(fs, clst);
 					if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; }
 					if (stat == 1) { res = FR_INT_ERR; break; }
 					if (stat == 0) n++;
-				} while (++clst < (*fatfs)->n_fatent);
+				} while (++clst < fs->n_fatent);
 			} else {
-				clst = (*fatfs)->n_fatent;
-				sect = (*fatfs)->fatbase;
+				clst = fs->n_fatent;
+				sect = fs->fatbase;
 				i = 0; p = 0;
 				do {
 					if (!i) {
-						res = move_window(*fatfs, sect++);
+						res = move_window(fs, sect++);
 						if (res != FR_OK) break;
-						p = (*fatfs)->win;
-						i = SS(*fatfs);
+						p = fs->win;
+						i = SS(fs);
 					}
 					if (fat == FS_FAT16) {
 						if (LD_WORD(p) == 0) n++;
@@ -3118,12 +3182,12 @@ FRESULT f_getfree (
 					}
 				} while (--clst);
 			}
-			(*fatfs)->free_clust = n;
-			if (fat == FS_FAT32) (*fatfs)->fsi_flag = 1;
+			fs->free_clust = n;
+			if (fat == FS_FAT32) fs->fsi_flag = 1;
 			*nclst = n;
 		}
 	}
-	LEAVE_FF(*fatfs, res);
+	LEAVE_FF(fs, res);
 }
 
 
@@ -3141,7 +3205,9 @@ FRESULT f_truncate (
 	DWORD ncl;
 
 
-	res = validate(fp->fs, fp->id);		/* Check validity of the object */
+	if (!fp) return FR_INVALID_OBJECT;
+
+	res = validate(fp);						/* Check validity of the object */
 	if (res == FR_OK) {
 		if (fp->flag & FA__ERROR) {			/* Check abort flag */
 			res = FR_INT_ERR;
@@ -3198,7 +3264,7 @@ FRESULT f_unlink (
 		res = follow_path(&dj, path);		/* Follow the file path */
 		if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT))
 			res = FR_INVALID_NAME;			/* Cannot remove dot entry */
-#if _FS_SHARE
+#if _FS_LOCK
 		if (res == FR_OK) res = chk_lock(&dj, 2);	/* Cannot remove open file */
 #endif
 		if (res == FR_OK) {					/* The object is accessible */
@@ -3209,19 +3275,19 @@ FRESULT f_unlink (
 				if (dir[DIR_Attr] & AM_RDO)
 					res = FR_DENIED;		/* Cannot remove R/O object */
 			}
-			dclst = LD_CLUST(dir);
+			dclst = ld_clust(dj.fs, dir);
 			if (res == FR_OK && (dir[DIR_Attr] & AM_DIR)) {	/* Is it a sub-dir? */
 				if (dclst < 2) {
 					res = FR_INT_ERR;
 				} else {
-					mem_cpy(&sdj, &dj, sizeof(DIR));	/* Check if the sub-dir is empty or not */
+					mem_cpy(&sdj, &dj, sizeof (DIR));	/* Check if the sub-dir is empty or not */
 					sdj.sclust = dclst;
 					res = dir_sdi(&sdj, 2);		/* Exclude dot entries */
 					if (res == FR_OK) {
 						res = dir_read(&sdj);
-						if (res == FR_OK			/* Not empty dir */
+						if (res == FR_OK		/* Not empty dir */
 #if _FS_RPATH
-						|| dclst == sdj.fs->cdir	/* Current dir */
+						|| dclst == dj.fs->cdir	/* Current dir */
 #endif
 						) res = FR_DENIED;
 						if (res == FR_NO_FILE) res = FR_OK;	/* Empty */
@@ -3283,12 +3349,12 @@ FRESULT f_mkdir (
 				dir[DIR_Name] = '.';
 				dir[DIR_Attr] = AM_DIR;
 				ST_DWORD(dir+DIR_WrtTime, tim);
-				ST_CLUST(dir, dcl);
+				st_clust(dir, dcl);
 				mem_cpy(dir+SZ_DIR, dir, SZ_DIR); 	/* Create ".." entry */
 				dir[33] = '.'; pcl = dj.sclust;
 				if (dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase)
 					pcl = 0;
-				ST_CLUST(dir+SZ_DIR, pcl);
+				st_clust(dir+SZ_DIR, pcl);
 				for (n = dj.fs->csize; n; n--) {	/* Write dot entries and clear following sectors */
 					dj.fs->winsect = dsc++;
 					dj.fs->wflag = 1;
@@ -3304,7 +3370,7 @@ FRESULT f_mkdir (
 				dir = dj.dir;
 				dir[DIR_Attr] = AM_DIR;				/* Attribute */
 				ST_DWORD(dir+DIR_WrtTime, tim);		/* Created time */
-				ST_CLUST(dir, dcl);					/* Table start cluster */
+				st_clust(dir, dcl);					/* Table start cluster */
 				dj.fs->wflag = 1;
 				res = sync(dj.fs);
 			}
@@ -3424,7 +3490,7 @@ FRESULT f_rename (
 		res = follow_path(&djo, path_old);		/* Check old object */
 		if (_FS_RPATH && res == FR_OK && (djo.fn[NS] & NS_DOT))
 			res = FR_INVALID_NAME;
-#if _FS_SHARE
+#if _FS_LOCK
 		if (res == FR_OK) res = chk_lock(&djo, 2);
 #endif
 		if (res == FR_OK) {						/* Old object is found */
@@ -3432,11 +3498,11 @@ FRESULT f_rename (
 				res = FR_NO_FILE;
 			} else {
 				mem_cpy(buf, djo.dir+DIR_Attr, 21);		/* Save the object information except for name */
-				mem_cpy(&djn, &djo, sizeof(DIR));		/* Check new object */
+				mem_cpy(&djn, &djo, sizeof (DIR));		/* Check new object */
 				res = follow_path(&djn, path_new);
 				if (res == FR_OK) res = FR_EXIST;		/* The new object name is already existing */
 				if (res == FR_NO_FILE) { 				/* Is it a valid path and no name collision? */
-/* Start critical section that any interruption or error can cause cross-link */
+/* Start critical section that an interruption or error can cause cross-link */
 					res = dir_register(&djn);			/* Register the new entry */
 					if (res == FR_OK) {
 						dir = djn.dir;					/* Copy object information except for name */
@@ -3444,16 +3510,16 @@ FRESULT f_rename (
 						dir[DIR_Attr] = buf[0] | AM_ARC;
 						djo.fs->wflag = 1;
 						if (djo.sclust != djn.sclust && (dir[DIR_Attr] & AM_DIR)) {		/* Update .. entry in the directory if needed */
-							dw = clust2sect(djn.fs, LD_CLUST(dir));
+							dw = clust2sect(djo.fs, ld_clust(djo.fs, dir));
 							if (!dw) {
 								res = FR_INT_ERR;
 							} else {
-								res = move_window(djn.fs, dw);
-								dir = djn.fs->win+SZ_DIR;	/* .. entry */
+								res = move_window(djo.fs, dw);
+								dir = djo.fs->win+SZ_DIR;	/* .. entry */
 								if (res == FR_OK && dir[1] == '.') {
-									dw = (djn.fs->fs_type == FS_FAT32 && djn.sclust == djn.fs->dirbase) ? 0 : djn.sclust;
-									ST_CLUST(dir, dw);
-									djn.fs->wflag = 1;
+									dw = (djo.fs->fs_type == FS_FAT32 && djn.sclust == djo.fs->dirbase) ? 0 : djn.sclust;
+									st_clust(dir, dw);
+									djo.fs->wflag = 1;
 								}
 							}
 						}
@@ -3497,9 +3563,11 @@ FRESULT f_forward (
 	BYTE csect;
 
 
-	*bf = 0;	/* Initialize byte counter */
+	*bf = 0;	/* Clear transfer byte counter */
+
+	if (!fp) return FR_INVALID_OBJECT;
 
-	res = validate(fp->fs, fp->id);					/* Check validity of the object */
+	res = validate(fp);								/* Check validity of the object */
 	if (res != FR_OK) LEAVE_FF(fp->fs, res);
 	if (fp->flag & FA__ERROR)						/* Check error flag */
 		LEAVE_FF(fp->fs, FR_INT_ERR);
@@ -3555,10 +3623,10 @@ FRESULT f_mkfs (
 {
 	static const WORD vst[] = { 1024,   512,  256,  128,   64,    32,   16,    8,    4,    2,   0};
 	static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512};
-	BYTE fmt, md, *tbl;
+	BYTE fmt, md, sys, *tbl, pdrv, part;
 	DWORD n_clst, vs, n, wsect;
 	UINT i;
-	DWORD b_vol, b_fat, b_dir, b_data;	/* Offset (LBA) */
+	DWORD b_vol, b_fat, b_dir, b_data;	/* LBA */
 	DWORD n_vol, n_rsv, n_fat, n_dir;	/* Size */
 	FATFS *fs;
 	DSTATUS stat;
@@ -3566,25 +3634,39 @@ FRESULT f_mkfs (
 
 	/* Check mounted drive and clear work area */
 	if (drv >= _VOLUMES) return FR_INVALID_DRIVE;
+	if (sfd > 1) return FR_INVALID_PARAMETER;
+	if (au & (au - 1)) return FR_INVALID_PARAMETER;
 	fs = FatFs[drv];
 	if (!fs) return FR_NOT_ENABLED;
 	fs->fs_type = 0;
-	drv = LD2PD(drv);
+	pdrv = LD2PD(drv);	/* Physical drive */
+	part = LD2PT(drv);	/* Partition (0:auto detect, 1-4:get from partition table)*/
 
 	/* Get disk statics */
-	stat = disk_initialize(drv);
+	stat = disk_initialize(pdrv);
 	if (stat & STA_NOINIT) return FR_NOT_READY;
 	if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
 #if _MAX_SS != 512					/* Get disk sector size */
-	if (disk_ioctl(drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK)
+	if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > _MAX_SS)
 		return FR_DISK_ERR;
 #endif
-	if (disk_ioctl(drv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128)
-		return FR_DISK_ERR;
-	b_vol = (sfd) ? 0 : 63;	/* Volume start sector */
-	n_vol -= b_vol;
-	if (au & (au - 1)) au = 0;	/* Check validity of the AU size */
-	if (!au) {					/* AU auto selection */
+	if (_MULTI_PARTITION && part) {
+		/* Get partition information from partition table in the MBR */
+		if (disk_read(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR;
+		if (LD_WORD(fs->win+BS_55AA) != 0xAA55) return FR_MKFS_ABORTED;
+		tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE];
+		if (!tbl[4]) return FR_MKFS_ABORTED;	/* No partition? */
+		b_vol = LD_DWORD(tbl+8);	/* Volume start sector */
+		n_vol = LD_DWORD(tbl+12);	/* Volume size */
+	} else {
+		/* Create a partition in this function */
+		if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128)
+			return FR_DISK_ERR;
+		b_vol = (sfd) ? 0 : 63;		/* Volume start sector */
+		n_vol -= b_vol;				/* Volume size */
+	}
+
+	if (!au) {				/* AU auto selection */
 		vs = n_vol / (2000 / (SS(fs) / 512));
 		for (i = 0; vs < vst[i]; i++) ;
 		au = cst[i];
@@ -3593,7 +3675,7 @@ FRESULT f_mkfs (
 	if (au == 0) au = 1;
 	if (au > 128) au = 128;
 
-	/* Pre-compute number of clusters and FAT syb-type */
+	/* Pre-compute number of clusters and FAT sub-type */
 	n_clst = n_vol / au;
 	fmt = FS_FAT12;
 	if (n_clst >= MIN_FAT16) fmt = FS_FAT16;
@@ -3613,10 +3695,10 @@ FRESULT f_mkfs (
 	b_fat = b_vol + n_rsv;				/* FAT area start sector */
 	b_dir = b_fat + n_fat * N_FATS;		/* Directory area start sector */
 	b_data = b_dir + n_dir;				/* Data area start sector */
-	if (n_vol < b_data + au) return FR_MKFS_ABORTED;	/* Too small volume */
+	if (n_vol < b_data + au - b_vol) return FR_MKFS_ABORTED;	/* Too small volume */
 
 	/* Align data start sector to erase block boundary (for flash memory media) */
-	if (disk_ioctl(drv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1;
+	if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1;
 	n = (b_data + n - 1) & ~(n - 1);	/* Next nearest erase block from current data start */
 	n = (n - b_data) / N_FATS;
 	if (fmt == FS_FAT32) {		/* FAT32: Move FAT offset */
@@ -3632,36 +3714,42 @@ FRESULT f_mkfs (
 		|| (fmt == FS_FAT32 && n_clst < MIN_FAT32))
 		return FR_MKFS_ABORTED;
 
-	/* Create partition table if required */
-	if (sfd) {	/* No partition table (SFD) */
-		md = 0xF0;
-	} else {	/* With partition table (FDISK) */
-		DWORD n_disk = b_vol + n_vol;
-
-		mem_set(fs->win, 0, SS(fs));
-		tbl = fs->win+MBR_Table;
-		ST_DWORD(tbl, 0x00010180);			/* Partition start in CHS */
-		if (n_disk < 63UL * 255 * 1024) {	/* Partition end in CHS */
-			n_disk = n_disk / 63 / 255;
-			tbl[7] = (BYTE)n_disk;
-			tbl[6] = (BYTE)((n_disk >> 2) | 63);
-		} else {
-			ST_WORD(&tbl[6], 0xFFFF);	/* CHS saturated */
-		}
-		tbl[5] = 254;
-		if (fmt != FS_FAT32)				/* System ID */
-			tbl[4] = (n_vol < 0x10000) ? 0x04 : 0x06;
-		else
-			tbl[4] = 0x0c;
-		ST_DWORD(tbl+8, 63);				/* Partition start in LBA */
-		ST_DWORD(tbl+12, n_vol);			/* Partition size in LBA */
-		ST_WORD(fs->win+BS_55AA, 0xAA55);	/* MBR signature */
-		if (disk_write(drv, fs->win, 0, 1) != RES_OK)	/* Put the MBR into first physical sector */
-			return FR_DISK_ERR;
+	switch (fmt) {	/* Determine system ID for partition table */
+	case FS_FAT12:	sys = 0x01; break;
+	case FS_FAT16:	sys = (n_vol < 0x10000) ? 0x04 : 0x06; break;
+	default: 		sys = 0x0C;
+	}
+
+	if (_MULTI_PARTITION && part) {
+		/* Update system ID in the partition table */
+		tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE];
+		tbl[4] = sys;
+		if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR;
 		md = 0xF8;
+	} else {
+		if (sfd) {	/* No partition table (SFD) */
+			md = 0xF0;
+		} else {	/* Create partition table (FDISK) */
+			mem_set(fs->win, 0, SS(fs));
+			tbl = fs->win+MBR_Table;	/* Create partition table for single partition in the drive */
+			tbl[1] = 1;						/* Partition start head */
+			tbl[2] = 1;						/* Partition start sector */
+			tbl[3] = 0;						/* Partition start cylinder */
+			tbl[4] = sys;					/* System type */
+			tbl[5] = 254;					/* Partition end head */
+			n = (b_vol + n_vol) / 63 / 255;
+			tbl[6] = (BYTE)((n >> 2) | 63);	/* Partition end sector */
+			tbl[7] = (BYTE)n;				/* End cylinder */
+			ST_DWORD(tbl+8, 63);			/* Partition start in LBA */
+			ST_DWORD(tbl+12, n_vol);		/* Partition size in LBA */
+			ST_WORD(fs->win+BS_55AA, 0xAA55);	/* MBR signature */
+			if (disk_write(pdrv, fs->win, 0, 1) != RES_OK)	/* Write it to the MBR sector */
+				return FR_DISK_ERR;
+			md = 0xF8;
+		}
 	}
 
-	/* Create volume boot record */
+	/* Create BPB in the VBR */
 	tbl = fs->win;							/* Clear sector */
 	mem_set(tbl, 0, SS(fs));
 	mem_cpy(tbl, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code, OEM name */
@@ -3699,10 +3787,10 @@ FRESULT f_mkfs (
 		mem_cpy(tbl+BS_VolLab, "NO NAME    " "FAT     ", 19);	/* Volume label, FAT signature */
 	}
 	ST_WORD(tbl+BS_55AA, 0xAA55);			/* Signature (Offset is fixed here regardless of sector size) */
-	if (disk_write(drv, tbl, b_vol, 1) != RES_OK)	/* Write VBR */
+	if (disk_write(pdrv, tbl, b_vol, 1) != RES_OK)	/* Write it to the VBR sector */
 		return FR_DISK_ERR;
 	if (fmt == FS_FAT32)							/* Write backup VBR if needed (VBR+6) */
-		disk_write(drv, tbl, b_vol + 6, 1);
+		disk_write(pdrv, tbl, b_vol + 6, 1);
 
 	/* Initialize FAT area */
 	wsect = b_fat;
@@ -3718,11 +3806,11 @@ FRESULT f_mkfs (
 			ST_DWORD(tbl+4, 0xFFFFFFFF);
 			ST_DWORD(tbl+8, 0x0FFFFFFF);	/* Reserve cluster #2 for root dir */
 		}
-		if (disk_write(drv, tbl, wsect++, 1) != RES_OK)
+		if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
 			return FR_DISK_ERR;
 		mem_set(tbl, 0, SS(fs));			/* Fill following FAT entries with zero */
 		for (n = 1; n < n_fat; n++) {		/* This loop may take a time on FAT32 volume due to many single sector writes */
-			if (disk_write(drv, tbl, wsect++, 1) != RES_OK)
+			if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
 				return FR_DISK_ERR;
 		}
 	}
@@ -3730,7 +3818,7 @@ FRESULT f_mkfs (
 	/* Initialize root directory */
 	i = (fmt == FS_FAT32) ? au : n_dir;
 	do {
-		if (disk_write(drv, tbl, wsect++, 1) != RES_OK)
+		if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
 			return FR_DISK_ERR;
 	} while (--i);
 
@@ -3739,7 +3827,7 @@ FRESULT f_mkfs (
 		DWORD eb[2];
 
 		eb[0] = wsect; eb[1] = wsect + (n_clst - ((fmt == FS_FAT32) ? 1 : 0)) * au - 1;
-		disk_ioctl(drv, CTRL_ERASE_SECTOR, eb);
+		disk_ioctl(pdrv, CTRL_ERASE_SECTOR, eb);
 	}
 #endif
 
@@ -3750,13 +3838,82 @@ FRESULT f_mkfs (
 		ST_DWORD(tbl+FSI_Free_Count, n_clst - 1);	/* Number of free clusters */
 		ST_DWORD(tbl+FSI_Nxt_Free, 2);				/* Last allocated cluster# */
 		ST_WORD(tbl+BS_55AA, 0xAA55);
-		disk_write(drv, tbl, b_vol + 1, 1);	/* Write original (VBR+1) */
-		disk_write(drv, tbl, b_vol + 7, 1);	/* Write backup (VBR+7) */
+		disk_write(pdrv, tbl, b_vol + 1, 1);	/* Write original (VBR+1) */
+		disk_write(pdrv, tbl, b_vol + 7, 1);	/* Write backup (VBR+7) */
+	}
+
+	return (disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR;
+}
+
+
+#if _MULTI_PARTITION == 2
+/*-----------------------------------------------------------------------*/
+/* Divide Physical Drive                                                 */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_fdisk (
+	BYTE pdrv,			/* Physical drive number */
+	const DWORD szt[],	/* Pointer to the size table for each partitions */
+	void* work			/* Pointer to the working buffer */
+)
+{
+	UINT i, n, sz_cyl, tot_cyl, b_cyl, e_cyl, p_cyl;
+	BYTE s_hd, e_hd, *p, *buf = (BYTE*)work;
+	DSTATUS stat;
+	DWORD sz_disk, sz_part, s_part;
+
+
+	stat = disk_initialize(pdrv);
+	if (stat & STA_NOINIT) return FR_NOT_READY;
+	if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
+	if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR;
+
+	/* Determine CHS in the table regardless of the drive geometry */
+	for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ;
+	if (n == 256) n--;
+	e_hd = n - 1;
+	sz_cyl = 63 * n;
+	tot_cyl = sz_disk / sz_cyl;
+
+	/* Create partition table */
+	mem_set(buf, 0, _MAX_SS);
+	p = buf + MBR_Table; b_cyl = 0;
+	for (i = 0; i < 4; i++, p += SZ_PTE) {
+		p_cyl = (szt[i] <= 100) ? (DWORD)tot_cyl * szt[i] / 100 : szt[i] / sz_cyl;
+		if (!p_cyl) continue;
+		s_part = (DWORD)sz_cyl * b_cyl;
+		sz_part = (DWORD)sz_cyl * p_cyl;
+		if (i == 0) {	/* Exclude first track of cylinder 0 */
+			s_hd = 1;
+			s_part += 63; sz_part -= 63;
+		} else {
+			s_hd = 0;
+		}
+		e_cyl = b_cyl + p_cyl - 1;
+		if (e_cyl >= tot_cyl) return FR_INVALID_PARAMETER;
+
+		/* Set partition table */
+		p[1] = s_hd;						/* Start head */
+		p[2] = (BYTE)((b_cyl >> 2) + 1);	/* Start sector */
+		p[3] = (BYTE)b_cyl;					/* Start cylinder */
+		p[4] = 0x06;						/* System type (temporary setting) */
+		p[5] = e_hd;						/* End head */
+		p[6] = (BYTE)((e_cyl >> 2) + 63);	/* End sector */
+		p[7] = (BYTE)e_cyl;					/* End cylinder */
+		ST_DWORD(p + 8, s_part);			/* Start sector in LBA */
+		ST_DWORD(p + 12, sz_part);			/* Partition size */
+
+		/* Next partition */
+		b_cyl += p_cyl;
 	}
+	ST_WORD(p, 0xAA55);
 
-	return (disk_ioctl(drv, CTRL_SYNC, (void*)0) == RES_OK) ? FR_OK : FR_DISK_ERR;
+	/* Write it to the MBR */
+	return (disk_write(pdrv, buf, 0, 1) || disk_ioctl(pdrv, CTRL_SYNC, 0)) ? FR_DISK_ERR : FR_OK;
 }
 
+
+#endif /* _MULTI_PARTITION == 2 */
 #endif /* _USE_MKFS && !_FS_READONLY */
 
 
@@ -3894,7 +4051,7 @@ int f_printf (
 	UINT i, j, w;
 	ULONG v;
 	TCHAR c, d, s[16], *p;
-	int res, cc;
+	int res, chc, cc;
 
 
 	va_start(arp, str);
@@ -3930,11 +4087,13 @@ int f_printf (
 		case 'S' :					/* String */
 			p = va_arg(arp, TCHAR*);
 			for (j = 0; p[j]; j++) ;
-			res = 0;
-			while (!(f & 2) && j++ < w) res += (cc = f_putc(' ', fil));
-			res += (cc = f_puts(p, fil));
-			while (j++ < w) res += (cc = f_putc(' ', fil));
-			if (cc != EOF) cc = res;
+			chc = 0;
+			if (!(f & 2)) {
+				while (j++ < w) chc += (cc = f_putc(' ', fil));
+			}
+			chc += (cc = f_puts(p, fil));
+			while (j++ < w) chc += (cc = f_putc(' ', fil));
+			if (cc != EOF) cc = chc;
 			continue;
 		case 'C' :					/* Character */
 			cc = f_putc((TCHAR)va_arg(arp, int), fil); continue;
@@ -3945,14 +4104,14 @@ int f_printf (
 		case 'D' :					/* Signed decimal */
 		case 'U' :					/* Unsigned decimal */
 			r = 10; break;
-		case 'X' :					/* Hexadecimal */
+		case 'X' :					/* Hexdecimal */
 			r = 16; break;
 		default:					/* Unknown type (pass-through) */
 			cc = f_putc(c, fil); continue;
 		}
 
 		/* Get an argument and put it in numeral */
-		v = (f & 4) ? va_arg(arp, long) : ((d == 'D') ? (long)va_arg(arp, int) : va_arg(arp, unsigned int));
+		v = (f & 4) ? (ULONG)va_arg(arp, long) : ((d == 'D') ? (ULONG)(long)va_arg(arp, int) : (ULONG)va_arg(arp, unsigned int));
 		if (d == 'D' && (v & 0x80000000)) {
 			v = 0 - v;
 			f |= 8;
@@ -3962,7 +4121,7 @@ int f_printf (
 			d = (TCHAR)(v % r); v /= r;
 			if (d > 9) d += (c == 'x') ? 0x27 : 0x07;
 			s[i++] = d + '0';
-		} while (v && i < sizeof(s) / sizeof(s[0]));
+		} while (v && i < sizeof s / sizeof s[0]);
 		if (f & 8) s[i++] = '-';
 		j = i; d = (f & 1) ? '0' : ' ';
 		res = 0;
@@ -3978,4 +4137,3 @@ int f_printf (
 
 #endif /* !_FS_READONLY */
 #endif /* _USE_STRFUNC */
-
diff --git a/Projects/TempDataLogger/Lib/FATFs/ff.h b/Projects/TempDataLogger/Lib/FATFs/ff.h
index 9788a6518..627cbaabe 100644
--- a/Projects/TempDataLogger/Lib/FATFs/ff.h
+++ b/Projects/TempDataLogger/Lib/FATFs/ff.h
@@ -1,11 +1,11 @@
 /*---------------------------------------------------------------------------/
-/  FatFs - FAT file system module include file  R0.08b    (C)ChaN, 2011
+/  FatFs - FAT file system module include file  R0.09a    (C)ChaN, 2012
 /----------------------------------------------------------------------------/
 / FatFs module is a generic FAT file system module for small embedded systems.
 / This is a free software that opened for education, research and commercial
 / developments under license policy of following terms.
 /
-/  Copyright (C) 2011, ChaN, all right reserved.
+/  Copyright (C) 2012, ChaN, all right reserved.
 /
 / * The FatFs module is a free software and there is NO WARRANTY.
 / * No restriction on use. You can use, modify and redistribute it for
@@ -15,7 +15,7 @@
 /----------------------------------------------------------------------------*/
 
 #ifndef _FATFS
-#define _FATFS	8237	/* Revision ID */
+#define _FATFS	4004	/* Revision ID */
 
 #ifdef __cplusplus
 extern "C" {
@@ -33,17 +33,17 @@ extern "C" {
 /* Definitions of volume management */
 
 #if _MULTI_PARTITION		/* Multiple partition configuration */
-#define LD2PD(vol) (VolToPart[vol].pd)	/* Get physical drive# */
-#define LD2PT(vol) (VolToPart[vol].pt)	/* Get partition# */
 typedef struct {
-	BYTE pd;	/* Physical drive# */
-	BYTE pt;	/* Partition # (0-3) */
+	BYTE pd;	/* Physical drive number */
+	BYTE pt;	/* Partition: 0:Auto detect, 1-4:Forced partition) */
 } PARTITION;
-extern const PARTITION VolToPart[];	/* Volume - Physical location resolution table */
+extern PARTITION VolToPart[];	/* Volume - Partition resolution table */
+#define LD2PD(vol) (VolToPart[vol].pd)	/* Get physical drive number */
+#define LD2PT(vol) (VolToPart[vol].pt)	/* Get partition index */
 
-#else						/* Single partition configuration */
-#define LD2PD(vol) (vol)	/* Logical drive# is bound to the same physical drive# */
-#define LD2PT(vol) 0		/* Always mounts the 1st partition */
+#else							/* Single partition configuration */
+#define LD2PD(vol) (BYTE)(vol)	/* Each logical drive is bound to the same physical drive number */
+#define LD2PT(vol) 0			/* Always mounts the 1st partition or in SFD */
 
 #endif
 
@@ -84,7 +84,7 @@ typedef struct {
 	WORD	id;				/* File system mount ID */
 	WORD	n_rootdir;		/* Number of root directory entries (FAT12/16) */
 #if _MAX_SS != 512
-	WORD	ssize;			/* Bytes per sector (512,1024,2048,4096) */
+	WORD	ssize;			/* Bytes per sector (512, 1024, 2048 or 4096) */
 #endif
 #if _FS_REENTRANT
 	_SYNC_t	sobj;			/* Identifier of sync object */
@@ -111,24 +111,24 @@ typedef struct {
 /* File object structure (FIL) */
 
 typedef struct {
-	FATFS*	fs;				/* Pointer to the owner file system object */
-	WORD	id;				/* Owner file system mount ID */
+	FATFS*	fs;				/* Pointer to the related file system object */
+	WORD	id;				/* File system mount ID of the related file system object */
 	BYTE	flag;			/* File status flags */
 	BYTE	pad1;
-	DWORD	fptr;			/* File read/write pointer (0 on file open) */
+	DWORD	fptr;			/* File read/write pointer (0ed on file open) */
 	DWORD	fsize;			/* File size */
-	DWORD	sclust;			/* File start cluster (0 when fsize==0) */
-	DWORD	clust;			/* Current cluster */
-	DWORD	dsect;			/* Current data sector */
+	DWORD	sclust;			/* File data start cluster (0:no data cluster, always 0 when fsize is 0) */
+	DWORD	clust;			/* Current cluster of fpter */
+	DWORD	dsect;			/* Current data sector of fpter */
 #if !_FS_READONLY
 	DWORD	dir_sect;		/* Sector containing the directory entry */
-	BYTE*	dir_ptr;		/* Ponter to the directory entry in the window */
+	BYTE*	dir_ptr;		/* Pointer to the directory entry in the window */
 #endif
 #if _USE_FASTSEEK
 	DWORD*	cltbl;			/* Pointer to the cluster link map table (null on file open) */
 #endif
-#if _FS_SHARE
-	UINT	lockid;			/* File lock ID (index of file semaphore table) */
+#if _FS_LOCK
+	UINT	lockid;			/* File lock ID (index of file semaphore table Files[]) */
 #endif
 #if !_FS_TINY
 	BYTE	buf[_MAX_SS];	/* File data read/write buffer */
@@ -176,24 +176,25 @@ typedef struct {
 
 typedef enum {
 	FR_OK = 0,				/* (0) Succeeded */
-	FR_DISK_ERR,			/* (1) A hard error occured in the low level disk I/O layer */
+	FR_DISK_ERR,			/* (1) A hard error occurred in the low level disk I/O layer */
 	FR_INT_ERR,				/* (2) Assertion failed */
 	FR_NOT_READY,			/* (3) The physical drive cannot work */
 	FR_NO_FILE,				/* (4) Could not find the file */
 	FR_NO_PATH,				/* (5) Could not find the path */
 	FR_INVALID_NAME,		/* (6) The path name format is invalid */
-	FR_DENIED,				/* (7) Acces denied due to prohibited access or directory full */
-	FR_EXIST,				/* (8) Acces denied due to prohibited access */
+	FR_DENIED,				/* (7) Access denied due to prohibited access or directory full */
+	FR_EXIST,				/* (8) Access denied due to prohibited access */
 	FR_INVALID_OBJECT,		/* (9) The file/directory object is invalid */
 	FR_WRITE_PROTECTED,		/* (10) The physical drive is write protected */
 	FR_INVALID_DRIVE,		/* (11) The logical drive number is invalid */
 	FR_NOT_ENABLED,			/* (12) The volume has no work area */
-	FR_NO_FILESYSTEM,		/* (13) There is no valid FAT volume on the physical drive */
+	FR_NO_FILESYSTEM,		/* (13) There is no valid FAT volume */
 	FR_MKFS_ABORTED,		/* (14) The f_mkfs() aborted due to any parameter error */
 	FR_TIMEOUT,				/* (15) Could not get a grant to access the volume within defined period */
 	FR_LOCKED,				/* (16) The operation is rejected according to the file sharing policy */
 	FR_NOT_ENOUGH_CORE,		/* (17) LFN working buffer could not be allocated */
-	FR_TOO_MANY_OPEN_FILES	/* (18) Number of open files > _FS_SHARE */
+	FR_TOO_MANY_OPEN_FILES,	/* (18) Number of open files > _FS_SHARE */
+	FR_INVALID_PARAMETER	/* (19) Given parameter is invalid */
 } FRESULT;
 
 
@@ -216,27 +217,28 @@ FRESULT f_sync (FIL*);								/* Flush cached data of a writing file */
 FRESULT f_unlink (const TCHAR*);					/* Delete an existing file or directory */
 FRESULT	f_mkdir (const TCHAR*);						/* Create a new directory */
 FRESULT f_chmod (const TCHAR*, BYTE, BYTE);			/* Change attribute of the file/dir */
-FRESULT f_utime (const TCHAR*, const FILINFO*);		/* Change time-stamp of the file/dir */
+FRESULT f_utime (const TCHAR*, const FILINFO*);		/* Change times-tamp of the file/dir */
 FRESULT f_rename (const TCHAR*, const TCHAR*);		/* Rename/Move a file or directory */
-FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*);	/* Forward data to the stream */
-FRESULT f_mkfs (BYTE, BYTE, UINT);					/* Create a file system on the drive */
 FRESULT f_chdrive (BYTE);							/* Change current drive */
 FRESULT f_chdir (const TCHAR*);						/* Change current directory */
 FRESULT f_getcwd (TCHAR*, UINT);					/* Get current directory */
+FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*);	/* Forward data to the stream */
+FRESULT f_mkfs (BYTE, BYTE, UINT);					/* Create a file system on the drive */
+FRESULT	f_fdisk (BYTE, const DWORD[], void*);		/* Divide a physical drive into some partitions */
 int f_putc (TCHAR, FIL*);							/* Put a character to the file */
 int f_puts (const TCHAR*, FIL*);					/* Put a string to the file */
 int f_printf (FIL*, const TCHAR*, ...);				/* Put a formatted string to the file */
 TCHAR* f_gets (TCHAR*, int, FIL*);					/* Get a string from the file */
 
-#ifndef EOF
-#define EOF (-1)
-#endif
-
 #define f_eof(fp) (((fp)->fptr == (fp)->fsize) ? 1 : 0)
 #define f_error(fp) (((fp)->flag & FA__ERROR) ? 1 : 0)
 #define f_tell(fp) ((fp)->fptr)
 #define f_size(fp) ((fp)->fsize)
 
+#ifndef EOF
+#define EOF (-1)
+#endif
+
 
 
 
@@ -308,7 +310,7 @@ int ff_del_syncobj (_SYNC_t);		/* Delete a sync object */
 #define AM_MASK	0x3F	/* Mask of defined bits */
 
 
-/* Fast seek function */
+/* Fast seek feature */
 #define CREATE_LINKMAP	0xFFFFFFFF
 
 
@@ -333,4 +335,3 @@ int ff_del_syncobj (_SYNC_t);		/* Delete a sync object */
 #endif
 
 #endif /* _FATFS */
-
diff --git a/Projects/TempDataLogger/Lib/FATFs/ffconf.h b/Projects/TempDataLogger/Lib/FATFs/ffconf.h
index 42528bbc3..63a4e7823 100644
--- a/Projects/TempDataLogger/Lib/FATFs/ffconf.h
+++ b/Projects/TempDataLogger/Lib/FATFs/ffconf.h
@@ -1,5 +1,5 @@
 /*---------------------------------------------------------------------------/
-/  FatFs - FAT file system module configuration file  R0.08b (C)ChaN, 2011
+/  FatFs - FAT file system module configuration file  R0.09a (C)ChaN, 2012
 /----------------------------------------------------------------------------/
 /
 / CAUTION! Do not forget to make clean the project after any changes to
@@ -7,7 +7,7 @@
 /
 /----------------------------------------------------------------------------*/
 #ifndef _FFCONF
-#define _FFCONF 8237	/* Revision ID */
+#define _FFCONF 4004	/* Revision ID */
 
 
 /*---------------------------------------------------------------------------/
@@ -36,7 +36,7 @@
 /   3: f_lseek is removed in addition to 2. */
 
 
-#define	_USE_STRFUNC	0	/* 0:Disable or 1/2:Enable */
+#define	_USE_STRFUNC	0	/* 0:Disable or 1-2:Enable */
 /* To enable string functions, set _USE_STRFUNC to 1 or 2. */
 
 
@@ -137,7 +137,7 @@
 /  and GET_SECTOR_SIZE command must be implememted to the disk_ioctl function. */
 
 
-#define	_MULTI_PARTITION	0	/* 0:Single partition or 1:Multiple partition */
+#define	_MULTI_PARTITION	0	/* 0:Single partition, 1/2:Enable multiple partition */
 /* When set to 0, each volume is bound to the same physical drive number and
 / it can mount only first primaly partition. When it is set to 1, each volume
 / is tied to the partitions listed in VolToPart[]. */
@@ -163,7 +163,8 @@
 /  When the byte order on the memory is big-endian or address miss-aligned word
 /  access results incorrect behavior, the _WORD_ACCESS must be set to 0.
 /  If it is not the case, the value can also be set to 1 to improve the
-/  performance and code size. */
+/  performance and code size.
+*/
 
 
 /* A header file that defines sync object types on the O/S, such as
@@ -181,9 +182,9 @@
 /      function must be added to the project. */
 
 
-#define	_FS_SHARE	0	/* 0:Disable or >=1:Enable */
-/* To enable file shareing feature, set _FS_SHARE to 1 or greater. The value
-   defines how many files can be opened simultaneously. */
+#define	_FS_LOCK	0	/* 0:Disable or >=1:Enable */
+/* To enable file lock control feature, set _FS_LOCK to 1 or greater.
+   The value defines how many files can be opened simultaneously. */
 
 
 #endif /* _FFCONFIG */
diff --git a/Projects/Webserver/Lib/FATFs/00readme.txt b/Projects/Webserver/Lib/FATFs/00readme.txt
index c78da3186..80d8843d1 100644
--- a/Projects/Webserver/Lib/FATFs/00readme.txt
+++ b/Projects/Webserver/Lib/FATFs/00readme.txt
@@ -1,4 +1,4 @@
-FatFs Module Source Files R0.08b                       (C)ChaN, 2011
+FatFs Module Source Files R0.09a                       (C)ChaN, 2012
 
 
 FILES
@@ -7,7 +7,8 @@ FILES
   ff.h       Common include file for FatFs and application module.
   ff.c       FatFs module.
   diskio.h   Common include file for FatFs and disk I/O module.
-  integer.h  Alternative type definitions for integer variables.
+  diskio.c   An example of glue function to attach existing disk I/O module to FatFs.
+  integer.h  Integer type definitions for FatFs.
   option     Optional external functions.
 
   Low level disk I/O module is not included in this archive because the FatFs
@@ -23,7 +24,7 @@ AGREEMENTS
  small embedded systems. This is a free software and is opened for education,
  research and commercial developments under license policy of following trems.
 
-  Copyright (C) 2011, ChaN, all right reserved.
+  Copyright (C) 2012, ChaN, all right reserved.
 
  * The FatFs module is a free software and there is NO WARRANTY.
  * No restriction on use. You can use, modify and redistribute it for
@@ -125,3 +126,10 @@ REVISION HISTORY
                        f_lseek() reports required table size on creating CLMP.
                        Extended format syntax of f_printf function.
                        Ignores duplicated directory separators in given path names.
+
+  Sep 06,'11 R0.09     f_mkfs() supports multiple partition to finish the multiple partition feature.
+                       Added f_fdisk(). (_MULTI_PARTITION = 2)
+
+  Aug 27,'12 R0.09a    Fixed assertion failure due to OS/2 EA on FAT12/16.
+                       Changed API rejects null object pointer to avoid crash.
+                       Changed option name _FS_SHARE to _FS_LOCK.
diff --git a/Projects/Webserver/Lib/FATFs/diskio.c b/Projects/Webserver/Lib/FATFs/diskio.c
index 64daad9cd..b119b1a40 100644
--- a/Projects/Webserver/Lib/FATFs/diskio.c
+++ b/Projects/Webserver/Lib/FATFs/diskio.c
@@ -38,7 +38,7 @@ DRESULT disk_read (
 	BYTE drv,		/* Physical drive number (0..) */
 	BYTE *buff,		/* Data buffer to store read data */
 	DWORD sector,	/* Sector address (LBA) */
-	BYTE count		/* Number of sectors to read (1..255) */
+	BYTE count		/* Number of sectors to read (1..128) */
 )
 {
 	DataflashManager_ReadBlocks_RAM(sector, count, buff);
@@ -55,7 +55,7 @@ DRESULT disk_write (
 	BYTE drv,			/* Physical drive number (0..) */
 	const BYTE *buff,	/* Data to be written */
 	DWORD sector,		/* Sector address (LBA) */
-	BYTE count			/* Number of sectors to write (1..255) */
+	BYTE count			/* Number of sectors to write (1..128) */
 )
 {
 	DataflashManager_WriteBlocks_RAM(sector, count, buff);
diff --git a/Projects/Webserver/Lib/FATFs/diskio.h b/Projects/Webserver/Lib/FATFs/diskio.h
index 0d3454366..65e3048a0 100644
--- a/Projects/Webserver/Lib/FATFs/diskio.h
+++ b/Projects/Webserver/Lib/FATFs/diskio.h
@@ -2,10 +2,12 @@
 /  Low level disk interface module include file
 /-----------------------------------------------------------------------*/
 
-#ifndef _DISKIO
+#ifndef _DISKIO_DEFINED
+#define _DISKIO_DEFINED
 
-#define _READONLY	0	/* 1: Read-only mode */
-#define _USE_IOCTL	0
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 #include "integer.h"
 #include "ff.h"
@@ -32,9 +34,7 @@ typedef enum {
 DSTATUS disk_initialize (BYTE);
 DSTATUS disk_status (BYTE);
 DRESULT disk_read (BYTE, BYTE*, DWORD, BYTE);
-#if	_READONLY == 0
 DRESULT disk_write (BYTE, const BYTE*, DWORD, BYTE);
-#endif
 DRESULT disk_ioctl (BYTE, BYTE, void*);
 
 
@@ -45,6 +45,8 @@ DRESULT disk_ioctl (BYTE, BYTE, void*);
 #define STA_PROTECT		0x04	/* Write protected */
 
 
-#define _DISKIO
+#ifdef __cplusplus
+}
 #endif
 
+#endif
diff --git a/Projects/Webserver/Lib/FATFs/ff.c b/Projects/Webserver/Lib/FATFs/ff.c
index cd1dda9be..2f58adf83 100644
--- a/Projects/Webserver/Lib/FATFs/ff.c
+++ b/Projects/Webserver/Lib/FATFs/ff.c
@@ -1,11 +1,11 @@
 /*----------------------------------------------------------------------------/
-/  FatFs - FAT file system module  R0.08b                 (C)ChaN, 2011
+/  FatFs - FAT file system module  R0.09a                 (C)ChaN, 2012
 /-----------------------------------------------------------------------------/
 / FatFs module is a generic FAT file system module for small embedded systems.
 / This is a free software that opened for education, research and commercial
 / developments under license policy of following terms.
 /
-/  Copyright (C) 2011, ChaN, all right reserved.
+/  Copyright (C) 2012, ChaN, all right reserved.
 /
 / * The FatFs module is a free software and there is NO WARRANTY.
 / * No restriction on use. You can use, modify and redistribute it for
@@ -86,7 +86,13 @@
 / Jan 15,'11 R0.08b Fast seek feature is also applied to f_read() and f_write().
 /                   f_lseek() reports required table size on creating CLMP.
 /                   Extended format syntax of f_printf function.
-/                   Ignores duplicated directory separators in given path names.
+/                   Ignores duplicated directory separators in given path name.
+/
+/ Sep 06,'11 R0.09  f_mkfs() supports multiple partition to finish the multiple partition feature.
+/                   Added f_fdisk(). (_MULTI_PARTITION = 2)
+/ Aug 27,'12 R0.09a Fixed assertion failure due to OS/2 EA on FAT12/16 volume.
+/                   Changed f_open() and f_opendir reject null object pointer to avoid crash.
+/                   Changed option name _FS_SHARE to _FS_LOCK.
 /---------------------------------------------------------------------------*/
 
 #include "ff.h"			/* FatFs configurations and declarations */
@@ -99,7 +105,7 @@
 
 ---------------------------------------------------------------------------*/
 
-#if _FATFS != 8237
+#if _FATFS != 4004	/* Revision ID */
 #error Wrong include file (ff.h).
 #endif
 
@@ -109,7 +115,7 @@
 #error Wrong sector size.
 #endif
 #if _MAX_SS != 512
-#define	SS(fs)	((fs)->ssize)	/* Multiple sector size */
+#define	SS(fs)	((fs)->ssize)	/* Variable sector size */
 #else
 #define	SS(fs)	512U			/* Fixed sector size */
 #endif
@@ -130,10 +136,10 @@
 #define	ABORT(fs, res)		{ fp->flag |= FA__ERROR; LEAVE_FF(fs, res); }
 
 
-/* File sharing feature */
-#if _FS_SHARE
+/* File access control feature */
+#if _FS_LOCK
 #if _FS_READONLY
-#error _FS_SHARE must be 0 on read-only cfg.
+#error _FS_LOCK must be 0 on read-only cfg.
 #endif
 typedef struct {
 	FATFS *fs;				/* File ID 1, volume (NULL:blank entry) */
@@ -144,10 +150,6 @@ typedef struct {
 #endif
 
 
-/* Misc definitions */
-#define LD_CLUST(dir)	(((DWORD)LD_WORD(dir+DIR_FstClusHI)<<16) | LD_WORD(dir+DIR_FstClusLO))
-#define ST_CLUST(dir,cl) {ST_WORD(dir+DIR_FstClusLO, cl); ST_WORD(dir+DIR_FstClusHI, (DWORD)cl>>16);}
-
 
 /* DBCS code ranges and SBCS extend char conversion table */
 
@@ -434,8 +436,10 @@ typedef struct {
 #define	DIR_Name			0	/* Short file name (11) */
 #define	DIR_Attr			11	/* Attribute (1) */
 #define	DIR_NTres			12	/* NT flag (1) */
+#define DIR_CrtTimeTenth	13	/* Created time sub-second (1) */
 #define	DIR_CrtTime			14	/* Created time (2) */
 #define	DIR_CrtDate			16	/* Created date (2) */
+#define DIR_LstAccDate		18	/* Last accessed date (2) */
 #define	DIR_FstClusHI		20	/* Higher 16-bit of first cluster (2) */
 #define	DIR_WrtTime			22	/* Modified time (2) */
 #define	DIR_WrtDate			24	/* Modified date (2) */
@@ -449,17 +453,22 @@ typedef struct {
 #define	SZ_DIR				32		/* Size of a directory entry */
 #define	LLE					0x40	/* Last long entry flag in LDIR_Ord */
 #define	DDE					0xE5	/* Deleted directory entry mark in DIR_Name[0] */
-#define	NDDE				0x05	/* Replacement of a character collides with DDE */
+#define	NDDE				0x05	/* Replacement of the character collides with DDE */
 
 
 /*------------------------------------------------------------*/
-/* Work area                                                  */
+/* Module private work area                                   */
+/*------------------------------------------------------------*/
+/* Note that uninitialized variables with static duration are
+/  zeroed/nulled at start-up. If not, the compiler or start-up
+/  routine is out of ANSI-C standard.
+*/
 
 #if _VOLUMES
 static
 FATFS *FatFs[_VOLUMES];	/* Pointer to the file system objects (logical drives) */
 #else
-#error Number of drives must not be 0.
+#error Number of volumes must not be 0.
 #endif
 
 static
@@ -470,28 +479,28 @@ static
 BYTE CurrVol;			/* Current drive */
 #endif
 
-#if _FS_SHARE
+#if _FS_LOCK
 static
-FILESEM	Files[_FS_SHARE];	/* File lock semaphores */
+FILESEM	Files[_FS_LOCK];	/* File lock semaphores */
 #endif
 
-#if _USE_LFN == 0			/* No LFN */
+#if _USE_LFN == 0			/* No LFN feature */
 #define	DEF_NAMEBUF			BYTE sfn[12]
 #define INIT_BUF(dobj)		(dobj).fn = sfn
 #define	FREE_BUF()
 
-#elif _USE_LFN == 1			/* LFN with static LFN working buffer */
+#elif _USE_LFN == 1			/* LFN feature with static working buffer */
 static WCHAR LfnBuf[_MAX_LFN+1];
 #define	DEF_NAMEBUF			BYTE sfn[12]
 #define INIT_BUF(dobj)		{ (dobj).fn = sfn; (dobj).lfn = LfnBuf; }
 #define	FREE_BUF()
 
-#elif _USE_LFN == 2 		/* LFN with dynamic LFN working buffer on the stack */
+#elif _USE_LFN == 2 		/* LFN feature with dynamic working buffer on the stack */
 #define	DEF_NAMEBUF			BYTE sfn[12]; WCHAR lbuf[_MAX_LFN+1]
 #define INIT_BUF(dobj)		{ (dobj).fn = sfn; (dobj).lfn = lbuf; }
 #define	FREE_BUF()
 
-#elif _USE_LFN == 3 		/* LFN with dynamic LFN working buffer on the heap */
+#elif _USE_LFN == 3 		/* LFN feature with dynamic working buffer on the heap */
 #define	DEF_NAMEBUF			BYTE sfn[12]; WCHAR *lfn
 #define INIT_BUF(dobj)		{ lfn = ff_memalloc((_MAX_LFN + 1) * 2); \
 							  if (!lfn) LEAVE_FF((dobj).fs, FR_NOT_ENOUGH_CORE); \
@@ -523,10 +532,10 @@ void mem_cpy (void* dst, const void* src, UINT cnt) {
 	const BYTE *s = (const BYTE*)src;
 
 #if _WORD_ACCESS == 1
-	while (cnt >= sizeof(int)) {
+	while (cnt >= sizeof (int)) {
 		*(int*)d = *(int*)s;
-		d += sizeof(int); s += sizeof(int);
-		cnt -= sizeof(int);
+		d += sizeof (int); s += sizeof (int);
+		cnt -= sizeof (int);
 	}
 #endif
 	while (cnt--)
@@ -581,7 +590,8 @@ void unlock_fs (
 	FRESULT res		/* Result code to be returned */
 )
 {
-	if (res != FR_NOT_ENABLED &&
+	if (fs &&
+		res != FR_NOT_ENABLED &&
 		res != FR_INVALID_DRIVE &&
 		res != FR_INVALID_OBJECT &&
 		res != FR_TIMEOUT) {
@@ -593,9 +603,9 @@ void unlock_fs (
 
 
 /*-----------------------------------------------------------------------*/
-/* File sharing control functions                                       */
+/* File lock control functions                                           */
 /*-----------------------------------------------------------------------*/
-#if _FS_SHARE
+#if _FS_LOCK
 
 static
 FRESULT chk_lock (	/* Check if the file can be accessed */
@@ -606,7 +616,7 @@ FRESULT chk_lock (	/* Check if the file can be accessed */
 	UINT i, be;
 
 	/* Search file semaphore table */
-	for (i = be = 0; i < _FS_SHARE; i++) {
+	for (i = be = 0; i < _FS_LOCK; i++) {
 		if (Files[i].fs) {	/* Existing entry */
 			if (Files[i].fs == dj->fs &&	 	/* Check if the file matched with an open file */
 				Files[i].clu == dj->sclust &&
@@ -615,7 +625,7 @@ FRESULT chk_lock (	/* Check if the file can be accessed */
 			be++;
 		}
 	}
-	if (i == _FS_SHARE)	/* The file is not opened */
+	if (i == _FS_LOCK)	/* The file is not opened */
 		return (be || acc == 2) ? FR_OK : FR_TOO_MANY_OPEN_FILES;	/* Is there a blank entry for new file? */
 
 	/* The file has been opened. Reject any open against writing file and all write mode open */
@@ -624,14 +634,12 @@ FRESULT chk_lock (	/* Check if the file can be accessed */
 
 
 static
-int enq_lock (	/* Check if an entry is available for a new file */
-	FATFS* fs	/* File system object */
-)
+int enq_lock (void)	/* Check if an entry is available for a new file */
 {
 	UINT i;
 
-	for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ;
-	return (i == _FS_SHARE) ? 0 : 1;
+	for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ;
+	return (i == _FS_LOCK) ? 0 : 1;
 }
 
 
@@ -644,15 +652,15 @@ UINT inc_lock (	/* Increment file open counter and returns its index (0:int erro
 	UINT i;
 
 
-	for (i = 0; i < _FS_SHARE; i++) {	/* Find the file */
+	for (i = 0; i < _FS_LOCK; i++) {	/* Find the file */
 		if (Files[i].fs == dj->fs &&
 			Files[i].clu == dj->sclust &&
 			Files[i].idx == dj->index) break;
 	}
 
-	if (i == _FS_SHARE) {				/* Not opened. Register it as new. */
-		for (i = 0; i < _FS_SHARE && Files[i].fs; i++) ;
-		if (i == _FS_SHARE) return 0;	/* No space to register (int err) */
+	if (i == _FS_LOCK) {				/* Not opened. Register it as new. */
+		for (i = 0; i < _FS_LOCK && Files[i].fs; i++) ;
+		if (i == _FS_LOCK) return 0;	/* No space to register (int err) */
 		Files[i].fs = dj->fs;
 		Files[i].clu = dj->sclust;
 		Files[i].idx = dj->index;
@@ -676,7 +684,7 @@ FRESULT dec_lock (	/* Decrement file open counter */
 	FRESULT res;
 
 
-	if (--i < _FS_SHARE) {
+	if (--i < _FS_LOCK) {
 		n = Files[i].ctr;
 		if (n == 0x100) n = 0;
 		if (n) n--;
@@ -697,7 +705,7 @@ void clear_lock (	/* Clear lock entries of the volume */
 {
 	UINT i;
 
-	for (i = 0; i < _FS_SHARE; i++) {
+	for (i = 0; i < _FS_LOCK; i++) {
 		if (Files[i].fs == fs) Files[i].fs = 0;
 	}
 }
@@ -776,7 +784,7 @@ FRESULT sync (	/* FR_OK: successful, FR_DISK_ERR: failed */
 			fs->fsi_flag = 0;
 		}
 		/* Make sure that no pending write process in the physical drive */
-		if (disk_ioctl(fs->drv, CTRL_SYNC, (void*)0) != RES_OK)
+		if (disk_ioctl(fs->drv, CTRL_SYNC, 0) != RES_OK)
 			res = FR_DISK_ERR;
 	}
 
@@ -870,7 +878,7 @@ FRESULT put_fat (
 	} else {
 		switch (fs->fs_type) {
 		case FS_FAT12 :
-			bc = clst; bc += bc / 2;
+			bc = (UINT)clst; bc += bc / 2;
 			res = move_window(fs, fs->fatbase + (bc / SS(fs)));
 			if (res != FR_OK) break;
 			p = &fs->win[bc % SS(fs)];
@@ -924,7 +932,7 @@ FRESULT remove_chain (
 	FRESULT res;
 	DWORD nxt;
 #if _USE_ERASE
-	DWORD scl = clst, ecl = clst, resion[2];
+	DWORD scl = clst, ecl = clst, rt[2];
 #endif
 
 	if (clst < 2 || clst >= fs->n_fatent) {	/* Check range */
@@ -944,12 +952,12 @@ FRESULT remove_chain (
 				fs->fsi_flag = 1;
 			}
 #if _USE_ERASE
-			if (ecl + 1 == nxt) {	/* Next cluster is contiguous */
+			if (ecl + 1 == nxt) {	/* Is next cluster contiguous? */
 				ecl = nxt;
-			} else {				/* End of contiguous clusters */
-				resion[0] = clust2sect(fs, scl);					/* Start sector */
-				resion[1] = clust2sect(fs, ecl) + fs->csize - 1;	/* End sector */
-				disk_ioctl(fs->drv, CTRL_ERASE_SECTOR, resion);		/* Erase the block */
+			} else {				/* End of contiguous clusters */ 
+				rt[0] = clust2sect(fs, scl);					/* Start sector */
+				rt[1] = clust2sect(fs, ecl) + fs->csize - 1;	/* End sector */
+				disk_ioctl(fs->drv, CTRL_ERASE_SECTOR, rt);		/* Erase the block */
 				scl = ecl = nxt;
 			}
 #endif
@@ -1040,7 +1048,7 @@ DWORD clmt_clust (	/* <2:Error, >=2:Cluster number */
 	tbl = fp->cltbl + 1;	/* Top of CLMT */
 	cl = ofs / SS(fp->fs) / fp->fs->csize;	/* Cluster order from top of the file */
 	for (;;) {
-		ncl = *tbl++;			/* Number of clusters in the fragment */
+		ncl = *tbl++;			/* Number of cluters in the fragment */
 		if (!ncl) return 0;		/* End of table? (error) */
 		if (cl < ncl) break;	/* In this fragment? */
 		cl -= ncl; tbl++;		/* Next fragment */
@@ -1058,7 +1066,7 @@ DWORD clmt_clust (	/* <2:Error, >=2:Cluster number */
 static
 FRESULT dir_sdi (
 	DIR *dj,		/* Pointer to directory object */
-	WORD idx		/* Directory index number */
+	WORD idx		/* Index of directory table */
 )
 {
 	DWORD clst;
@@ -1100,7 +1108,7 @@ FRESULT dir_sdi (
 
 
 /*-----------------------------------------------------------------------*/
-/* Directory handling - Move directory index next                        */
+/* Directory handling - Move directory table index next                  */
 /*-----------------------------------------------------------------------*/
 
 static
@@ -1113,6 +1121,7 @@ FRESULT dir_next (	/* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT an
 	WORD i;
 
 
+	stretch = stretch;		/* To suppress warning on read-only cfg. */
 	i = dj->index + 1;
 	if (!i || !dj->sect)	/* Report EOT when index has reached 65535 */
 		return FR_NO_FILE;
@@ -1166,6 +1175,40 @@ FRESULT dir_next (	/* FR_OK:Succeeded, FR_NO_FILE:End of table, FR_DENIED:EOT an
 
 
 
+/*-----------------------------------------------------------------------*/
+/* Directory handling - Load/Store start cluster number                  */
+/*-----------------------------------------------------------------------*/
+
+static
+DWORD ld_clust (
+	FATFS *fs,	/* Pointer to the fs object */
+	BYTE *dir	/* Pointer to the directory entry */
+)
+{
+	DWORD cl;
+
+	cl = LD_WORD(dir+DIR_FstClusLO);
+	if (fs->fs_type == FS_FAT32)
+		cl |= (DWORD)LD_WORD(dir+DIR_FstClusHI) << 16;
+
+	return cl;
+}
+
+
+#if !_FS_READONLY
+static
+void st_clust (
+	BYTE *dir,	/* Pointer to the directory entry */
+	DWORD cl	/* Value to be set */
+)
+{
+	ST_WORD(dir+DIR_FstClusLO, cl);
+	ST_WORD(dir+DIR_FstClusHI, cl >> 16);
+}
+#endif
+
+
+
 /*-----------------------------------------------------------------------*/
 /* LFN handling - Test/Pick/Fit an LFN segment from/to directory entry   */
 /*-----------------------------------------------------------------------*/
@@ -1777,7 +1820,7 @@ FRESULT create_name (
 		if (c >= 0x80) {				/* Extended char? */
 			b |= 3;						/* Eliminate NT flag */
 #ifdef _EXCVT
-			c = excvt[c-0x80];			/* Upper conversion (SBCS) */
+			c = excvt[c - 0x80];		/* Upper conversion (SBCS) */
 #else
 #if !_DF1S	/* ASCII only cfg */
 			return FR_INVALID_NAME;
@@ -1933,7 +1976,6 @@ FRESULT follow_path (	/* FR_OK(0): successful, !=0: error code */
 	if ((UINT)*path < ' ') {			/* Nul path means the start directory itself */
 		res = dir_sdi(dj, 0);
 		dj->dir = 0;
-
 	} else {							/* Follow path */
 		for (;;) {
 			res = create_name(dj, &path);	/* Get a segment */
@@ -1957,7 +1999,7 @@ FRESULT follow_path (	/* FR_OK(0): successful, !=0: error code */
 			if (!(dir[DIR_Attr] & AM_DIR)) {	/* Cannot follow because it is a file */
 				res = FR_NO_PATH; break;
 			}
-			dj->sclust = LD_CLUST(dir);
+			dj->sclust = ld_clust(dj->fs, dir);
 		}
 	}
 
@@ -1968,11 +2010,11 @@ FRESULT follow_path (	/* FR_OK(0): successful, !=0: error code */
 
 
 /*-----------------------------------------------------------------------*/
-/* Load boot record and check if it is an FAT boot record                */
+/* Load a sector and check if it is an FAT Volume Boot Record            */
 /*-----------------------------------------------------------------------*/
 
 static
-BYTE check_fs (	/* 0:The FAT BR, 1:Valid BR but not an FAT, 2:Not a BR, 3:Disk error */
+BYTE check_fs (	/* 0:FAT-VBR, 1:Any BR but not FAT, 2:Not a BR, 3:Disk error */
 	FATFS *fs,	/* File system object */
 	DWORD sect	/* Sector# (lba) to check if it is an FAT boot record or not */
 )
@@ -2001,10 +2043,10 @@ static
 FRESULT chk_mounted (	/* FR_OK(0): successful, !=0: any error occurred */
 	const TCHAR **path,	/* Pointer to pointer to the path name (drive number) */
 	FATFS **rfs,		/* Pointer to pointer to the found file system object */
-	BYTE chk_wp			/* !=0: Check media write protection for write access */
+	BYTE wmode			/* !=0: Check write protection for write access */
 )
 {
-	BYTE fmt, b, *tbl;
+	BYTE fmt, b, pi, *tbl;
 	UINT vol;
 	DSTATUS stat;
 	DWORD bsect, fasize, tsect, sysect, nclst, szbfat;
@@ -2012,6 +2054,7 @@ FRESULT chk_mounted (	/* FR_OK(0): successful, !=0: any error occurred */
 	const TCHAR *p = *path;
 	FATFS *fs;
 
+
 	/* Get logical drive number from the path name */
 	vol = p[0] - '0';					/* Is there a drive number? */
 	if (vol <= 9 && p[1] == ':') {		/* Found a drive number, get and strip it */
@@ -2024,55 +2067,56 @@ FRESULT chk_mounted (	/* FR_OK(0): successful, !=0: any error occurred */
 #endif
 	}
 
-	/* Check if the logical drive is valid or not */
+	/* Check if the file system object is valid or not */
+	*rfs = 0;
 	if (vol >= _VOLUMES) 				/* Is the drive number valid? */
 		return FR_INVALID_DRIVE;
-	*rfs = fs = FatFs[vol];				/* Return pointer to the corresponding file system object */
+	fs = FatFs[vol];					/* Get corresponding file system object */
 	if (!fs) return FR_NOT_ENABLED;		/* Is the file system object available? */
 
 	ENTER_FF(fs);						/* Lock file system */
 
-	if (fs->fs_type) {					/* If the logical drive has been mounted */
+	*rfs = fs;							/* Return pointer to the corresponding file system object */
+	if (fs->fs_type) {					/* If the volume has been mounted */
 		stat = disk_status(fs->drv);
 		if (!(stat & STA_NOINIT)) {		/* and the physical drive is kept initialized (has not been changed), */
-#if !_FS_READONLY
-			if (chk_wp && (stat & STA_PROTECT))	/* Check write protection if needed */
+			if (!_FS_READONLY && wmode && (stat & STA_PROTECT))	/* Check write protection if needed */
 				return FR_WRITE_PROTECTED;
-#endif
 			return FR_OK;				/* The file system object is valid */
 		}
 	}
 
-	/* The logical drive must be mounted. */
-	/* Following code attempts to mount a volume. (analyze BPB and initialize the fs object) */
+	/* The file system object is not valid. */
+	/* Following code attempts to mount the volume. (analyze BPB and initialize the fs object) */
 
 	fs->fs_type = 0;					/* Clear the file system object */
-	fs->drv = (BYTE)LD2PD(vol);			/* Bind the logical drive and a physical drive */
-	stat = disk_initialize(fs->drv);	/* Initialize low level disk I/O layer */
+	fs->drv = LD2PD(vol);				/* Bind the logical drive and a physical drive */
+	stat = disk_initialize(fs->drv);	/* Initialize the physical drive */
 	if (stat & STA_NOINIT)				/* Check if the initialization succeeded */
-		return FR_NOT_READY;			/* Failed to initialize due to no media or hard error */
+		return FR_NOT_READY;			/* Failed to initialize due to no medium or hard error */
+	if (!_FS_READONLY && wmode && (stat & STA_PROTECT))	/* Check disk write protection if needed */
+		return FR_WRITE_PROTECTED;
 #if _MAX_SS != 512						/* Get disk sector size (variable sector size cfg only) */
 	if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &fs->ssize) != RES_OK)
 		return FR_DISK_ERR;
 #endif
-#if !_FS_READONLY
-	if (chk_wp && (stat & STA_PROTECT))	/* Check disk write protection if needed */
-		return FR_WRITE_PROTECTED;
-#endif
-	/* Search FAT partition on the drive. Supports only generic partitioning, FDISK and SFD. */
-	fmt = check_fs(fs, bsect = 0);		/* Check sector 0 if it is a VBR */
-	if (fmt == 1) {						/* Not an FAT-VBR, the disk may be partitioned */
-		/* Check the partition listed in top of the partition table */
-		tbl = &fs->win[MBR_Table + LD2PT(vol) * SZ_PTE];/* Partition table */
-		if (tbl[4]) {									/* Is the partition existing? */
-			bsect = LD_DWORD(&tbl[8]);					/* Partition offset in LBA */
-			fmt = check_fs(fs, bsect);					/* Check the partition */
+	/* Search FAT partition on the drive. Supports only generic partitions, FDISK and SFD. */
+	fmt = check_fs(fs, bsect = 0);		/* Load sector 0 and check if it is an FAT-VBR (in SFD) */
+	if (LD2PT(vol) && !fmt) fmt = 1;	/* Force non-SFD if the volume is forced partition */
+	if (fmt == 1) {						/* Not an FAT-VBR, the physical drive can be partitioned */
+		/* Check the partition listed in the partition table */
+		pi = LD2PT(vol);
+		if (pi) pi--;
+		tbl = &fs->win[MBR_Table + pi * SZ_PTE];/* Partition table */
+		if (tbl[4]) {						/* Is the partition existing? */
+			bsect = LD_DWORD(&tbl[8]);		/* Partition offset in LBA */
+			fmt = check_fs(fs, bsect);		/* Check the partition */
 		}
 	}
 	if (fmt == 3) return FR_DISK_ERR;
-	if (fmt) return FR_NO_FILESYSTEM;					/* No FAT volume is found */
+	if (fmt) return FR_NO_FILESYSTEM;		/* No FAT volume is found */
 
-	/* Following code initializes the file system object */
+	/* An FAT volume is found. Following code initializes the file system object */
 
 	if (LD_WORD(fs->win+BPB_BytsPerSec) != SS(fs))		/* (BPB_BytsPerSec must be equal to the physical sector size) */
 		return FR_NO_FILESYSTEM;
@@ -2148,7 +2192,7 @@ FRESULT chk_mounted (	/* FR_OK(0): successful, !=0: any error occurred */
 #if _FS_RPATH
 	fs->cdir = 0;			/* Current directory (root dir) */
 #endif
-#if _FS_SHARE				/* Clear file lock semaphores */
+#if _FS_LOCK				/* Clear file lock semaphores */
 	clear_lock(fs);
 #endif
 
@@ -2164,16 +2208,19 @@ FRESULT chk_mounted (	/* FR_OK(0): successful, !=0: any error occurred */
 
 static
 FRESULT validate (	/* FR_OK(0): The object is valid, !=0: Invalid */
-	FATFS *fs,		/* Pointer to the file system object */
-	WORD id			/* Member id of the target object to be checked */
+	void* obj		/* Pointer to the object FIL/DIR to check validity */
 )
 {
-	if (!fs || !fs->fs_type || fs->id != id)
+	FIL *fil;
+
+
+	fil = (FIL*)obj;	/* Assuming offset of fs and id in the FIL/DIR is identical */
+	if (!fil->fs || !fil->fs->fs_type || fil->fs->id != fil->id)
 		return FR_INVALID_OBJECT;
 
-	ENTER_FF(fs);		/* Lock file system */
+	ENTER_FF(fil->fs);		/* Lock file system */
 
-	if (disk_status(fs->drv) & STA_NOINIT)
+	if (disk_status(fil->fs->drv) & STA_NOINIT)
 		return FR_NOT_READY;
 
 	return FR_OK;
@@ -2202,27 +2249,27 @@ FRESULT f_mount (
 	FATFS *rfs;
 
 
-	if (vol >= _VOLUMES)			/* Check if the drive number is valid */
+	if (vol >= _VOLUMES)		/* Check if the drive number is valid */
 		return FR_INVALID_DRIVE;
-	rfs = FatFs[vol];				/* Get current fs object */
+	rfs = FatFs[vol];			/* Get current fs object */
 
 	if (rfs) {
-#if _FS_SHARE
+#if _FS_LOCK
 		clear_lock(rfs);
 #endif
-#if _FS_REENTRANT					/* Discard sync object of the current volume */
+#if _FS_REENTRANT				/* Discard sync object of the current volume */
 		if (!ff_del_syncobj(rfs->sobj)) return FR_INT_ERR;
 #endif
-		rfs->fs_type = 0;			/* Clear old fs object */
+		rfs->fs_type = 0;		/* Clear old fs object */
 	}
 
 	if (fs) {
-		fs->fs_type = 0;			/* Clear new fs object */
-#if _FS_REENTRANT					/* Create sync object for the new volume */
+		fs->fs_type = 0;		/* Clear new fs object */
+#if _FS_REENTRANT				/* Create sync object for the new volume */
 		if (!ff_cre_syncobj(vol, &fs->sobj)) return FR_INT_ERR;
 #endif
 	}
-	FatFs[vol] = fs;				/* Register new fs object */
+	FatFs[vol] = fs;			/* Register new fs object */
 
 	return FR_OK;
 }
@@ -2246,6 +2293,7 @@ FRESULT f_open (
 	DEF_NAMEBUF;
 
 
+	if (!fp) return FR_INVALID_OBJECT;
 	fp->fs = 0;			/* Clear file object */
 
 #if !_FS_READONLY
@@ -2255,103 +2303,104 @@ FRESULT f_open (
 	mode &= FA_READ;
 	res = chk_mounted(&path, &dj.fs, 0);
 #endif
-	INIT_BUF(dj);
-	if (res == FR_OK)
+	if (res == FR_OK) {
+		INIT_BUF(dj);
 		res = follow_path(&dj, path);	/* Follow the file path */
-	dir = dj.dir;
-
+		dir = dj.dir;
 #if !_FS_READONLY	/* R/W configuration */
-	if (res == FR_OK) {
-		if (!dir)	/* Current dir itself */
-			res = FR_INVALID_NAME;
-#if _FS_SHARE
-		else
-			res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
+		if (res == FR_OK) {
+			if (!dir)	/* Current dir itself */
+				res = FR_INVALID_NAME;
+#if _FS_LOCK
+			else
+				res = chk_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
 #endif
-	}
-	/* Create or Open a file */
-	if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) {
-		DWORD dw, cl;
-
-		if (res != FR_OK) {					/* No file, create new */
-			if (res == FR_NO_FILE)			/* There is no file to open, create a new entry */
-#if _FS_SHARE
-				res = enq_lock(dj.fs) ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES;
+		}
+		/* Create or Open a file */
+		if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) {
+			DWORD dw, cl;
+
+			if (res != FR_OK) {					/* No file, create new */
+				if (res == FR_NO_FILE)			/* There is no file to open, create a new entry */
+#if _FS_LOCK
+					res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES;
 #else
-				res = dir_register(&dj);
+					res = dir_register(&dj);
 #endif
-			mode |= FA_CREATE_ALWAYS;		/* File is created */
-			dir = dj.dir;					/* New entry */
-		}
-		else {								/* Any object is already existing */
-			if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) {	/* Cannot overwrite it (R/O or DIR) */
-				res = FR_DENIED;
-			} else {
-				if (mode & FA_CREATE_NEW)	/* Cannot create as new file */
-					res = FR_EXIST;
+				mode |= FA_CREATE_ALWAYS;		/* File is created */
+				dir = dj.dir;					/* New entry */
 			}
-		}
-		if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) {	/* Truncate it if overwrite mode */
-			dw = get_fattime();					/* Created time */
-			ST_DWORD(dir+DIR_CrtTime, dw);
-			dir[DIR_Attr] = 0;					/* Reset attribute */
-			ST_DWORD(dir+DIR_FileSize, 0);		/* size = 0 */
-			cl = LD_CLUST(dir);					/* Get start cluster */
-			ST_CLUST(dir, 0);					/* cluster = 0 */
-			dj.fs->wflag = 1;
-			if (cl) {							/* Remove the cluster chain if exist */
-				dw = dj.fs->winsect;
-				res = remove_chain(dj.fs, cl);
-				if (res == FR_OK) {
-					dj.fs->last_clust = cl - 1;	/* Reuse the cluster hole */
-					res = move_window(dj.fs, dw);
+			else {								/* Any object is already existing */
+				if (dir[DIR_Attr] & (AM_RDO | AM_DIR)) {	/* Cannot overwrite it (R/O or DIR) */
+					res = FR_DENIED;
+				} else {
+					if (mode & FA_CREATE_NEW)	/* Cannot create as new file */
+						res = FR_EXIST;
+				}
+			}
+			if (res == FR_OK && (mode & FA_CREATE_ALWAYS)) {	/* Truncate it if overwrite mode */
+				dw = get_fattime();					/* Created time */
+				ST_DWORD(dir+DIR_CrtTime, dw);
+				dir[DIR_Attr] = 0;					/* Reset attribute */
+				ST_DWORD(dir+DIR_FileSize, 0);		/* size = 0 */
+				cl = ld_clust(dj.fs, dir);			/* Get start cluster */
+				st_clust(dir, 0);					/* cluster = 0 */
+				dj.fs->wflag = 1;
+				if (cl) {							/* Remove the cluster chain if exist */
+					dw = dj.fs->winsect;
+					res = remove_chain(dj.fs, cl);
+					if (res == FR_OK) {
+						dj.fs->last_clust = cl - 1;	/* Reuse the cluster hole */
+						res = move_window(dj.fs, dw);
+					}
 				}
 			}
 		}
-	}
-	else {	/* Open an existing file */
-		if (res == FR_OK) {						/* Follow succeeded */
-			if (dir[DIR_Attr] & AM_DIR) {		/* It is a directory */
-				res = FR_NO_FILE;
-			} else {
-				if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */
-					res = FR_DENIED;
+		else {	/* Open an existing file */
+			if (res == FR_OK) {						/* Follow succeeded */
+				if (dir[DIR_Attr] & AM_DIR) {		/* It is a directory */
+					res = FR_NO_FILE;
+				} else {
+					if ((mode & FA_WRITE) && (dir[DIR_Attr] & AM_RDO)) /* R/O violation */
+						res = FR_DENIED;
+				}
 			}
 		}
-	}
-	if (res == FR_OK) {
-		if (mode & FA_CREATE_ALWAYS)			/* Set file change flag if created or overwritten */
-			mode |= FA__WRITTEN;
-		fp->dir_sect = dj.fs->winsect;			/* Pointer to the directory entry */
-		fp->dir_ptr = dir;
-#if _FS_SHARE
-		fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
-		if (!fp->lockid) res = FR_INT_ERR;
+		if (res == FR_OK) {
+			if (mode & FA_CREATE_ALWAYS)			/* Set file change flag if created or overwritten */
+				mode |= FA__WRITTEN;
+			fp->dir_sect = dj.fs->winsect;			/* Pointer to the directory entry */
+			fp->dir_ptr = dir;
+#if _FS_LOCK
+			fp->lockid = inc_lock(&dj, (mode & ~FA_READ) ? 1 : 0);
+			if (!fp->lockid) res = FR_INT_ERR;
 #endif
-	}
+		}
 
 #else				/* R/O configuration */
-	if (res == FR_OK) {					/* Follow succeeded */
-		if (!dir) {						/* Current dir itself */
-			res = FR_INVALID_NAME;
-		} else {
-			if (dir[DIR_Attr] & AM_DIR)	/* It is a directory */
-				res = FR_NO_FILE;
+		if (res == FR_OK) {					/* Follow succeeded */
+			dir = dj.dir;
+			if (!dir) {						/* Current dir itself */
+				res = FR_INVALID_NAME;
+			} else {
+				if (dir[DIR_Attr] & AM_DIR)	/* It is a directory */
+					res = FR_NO_FILE;
+			}
 		}
-	}
 #endif
-	FREE_BUF();
+		FREE_BUF();
 
-	if (res == FR_OK) {
-		fp->flag = mode;					/* File access mode */
-		fp->sclust = LD_CLUST(dir);			/* File start cluster */
-		fp->fsize = LD_DWORD(dir+DIR_FileSize);	/* File size */
-		fp->fptr = 0;						/* File pointer */
-		fp->dsect = 0;
+		if (res == FR_OK) {
+			fp->flag = mode;					/* File access mode */
+			fp->sclust = ld_clust(dj.fs, dir);	/* File start cluster */
+			fp->fsize = LD_DWORD(dir+DIR_FileSize);	/* File size */
+			fp->fptr = 0;						/* File pointer */
+			fp->dsect = 0;
 #if _USE_FASTSEEK
-		fp->cltbl = 0;						/* Normal seek mode */
+			fp->cltbl = 0;						/* Normal seek mode */
 #endif
-		fp->fs = dj.fs; fp->id = dj.fs->id;	/* Validate file object */
+			fp->fs = dj.fs; fp->id = dj.fs->id;	/* Validate file object */
+		}
 	}
 
 	LEAVE_FF(dj.fs, res);
@@ -2377,9 +2426,9 @@ FRESULT f_read (
 	BYTE csect, *rbuff = buff;
 
 
-	*br = 0;	/* Initialize byte counter */
+	*br = 0;	/* Clear read byte counter */
 
-	res = validate(fp->fs, fp->id);				/* Check validity */
+	res = validate(fp);							/* Check validity */
 	if (res != FR_OK) LEAVE_FF(fp->fs, res);
 	if (fp->flag & FA__ERROR)					/* Aborted file? */
 		LEAVE_FF(fp->fs, FR_INT_ERR);
@@ -2443,7 +2492,7 @@ FRESULT f_read (
 #endif
 			fp->dsect = sect;
 		}
-		rcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs));	/* Get partial sector data from sector buffer */
+		rcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs));	/* Get partial sector data from sector buffer */
 		if (rcnt > btr) rcnt = btr;
 #if _FS_TINY
 		if (move_window(fp->fs, fp->dsect))		/* Move sector window */
@@ -2479,9 +2528,9 @@ FRESULT f_write (
 	BYTE csect;
 
 
-	*bw = 0;	/* Initialize byte counter */
+	*bw = 0;	/* Clear write byte counter */
 
-	res = validate(fp->fs, fp->id);			/* Check validity */
+	res = validate(fp);						/* Check validity */
 	if (res != FR_OK) LEAVE_FF(fp->fs, res);
 	if (fp->flag & FA__ERROR)				/* Aborted file? */
 		LEAVE_FF(fp->fs, FR_INT_ERR);
@@ -2558,7 +2607,7 @@ FRESULT f_write (
 #endif
 			fp->dsect = sect;
 		}
-		wcnt = SS(fp->fs) - (fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */
+		wcnt = SS(fp->fs) - ((UINT)fp->fptr % SS(fp->fs));/* Put partial sector into file I/O buffer */
 		if (wcnt > btw) wcnt = btw;
 #if _FS_TINY
 		if (move_window(fp->fs, fp->dsect))	/* Move sector window */
@@ -2593,7 +2642,7 @@ FRESULT f_sync (
 	BYTE *dir;
 
 
-	res = validate(fp->fs, fp->id);		/* Check validity of the object */
+	res = validate(fp);					/* Check validity of the object */
 	if (res == FR_OK) {
 		if (fp->flag & FA__WRITTEN) {	/* Has the file been written? */
 #if !_FS_TINY	/* Write-back dirty buffer */
@@ -2609,9 +2658,10 @@ FRESULT f_sync (
 				dir = fp->dir_ptr;
 				dir[DIR_Attr] |= AM_ARC;					/* Set archive bit */
 				ST_DWORD(dir+DIR_FileSize, fp->fsize);		/* Update file size */
-				ST_CLUST(dir, fp->sclust);					/* Update start cluster */
+				st_clust(dir, fp->sclust);					/* Update start cluster */
 				tim = get_fattime();						/* Update updated time */
 				ST_DWORD(dir+DIR_WrtTime, tim);
+				ST_WORD(dir+DIR_LstAccDate, 0);
 				fp->flag &= ~FA__WRITTEN;
 				fp->fs->wflag = 1;
 				res = sync(fp->fs);
@@ -2637,21 +2687,26 @@ FRESULT f_close (
 {
 	FRESULT res;
 
-#if _FS_READONLY
-	FATFS *fs = fp->fs;
-	res = validate(fs, fp->id);
-	if (res == FR_OK) fp->fs = 0;	/* Discard file object */
-	LEAVE_FF(fs, res);
 
+#if _FS_READONLY
+	res = validate(fp);
+	{
+#if _FS_REENTRANT
+		FATFS *fs = fp->fs;
+#endif
+		if (res == FR_OK) fp->fs = 0;	/* Discard file object */
+		LEAVE_FF(fs, res);
+	}
 #else
 	res = f_sync(fp);		/* Flush cached data */
-#if _FS_SHARE
+#if _FS_LOCK
 	if (res == FR_OK) {		/* Decrement open counter */
 #if _FS_REENTRANT
-		res = validate(fp->fs, fp->id);
+		FATFS *fs = fp->fs;;
+		res = validate(fp);
 		if (res == FR_OK) {
-			res = dec_lock(fp->lockid);
-			unlock_fs(fp->fs, FR_OK);
+			res = dec_lock(fp->lockid);	
+			unlock_fs(fs, FR_OK);
 		}
 #else
 		res = dec_lock(fp->lockid);
@@ -2704,7 +2759,7 @@ FRESULT f_chdir (
 				dj.fs->cdir = dj.sclust;	/* Start directory itself */
 			} else {
 				if (dj.dir[DIR_Attr] & AM_DIR)	/* Reached to the directory */
-					dj.fs->cdir = LD_CLUST(dj.dir);
+					dj.fs->cdir = ld_clust(dj.fs, dj.dir);
 				else
 					res = FR_NO_PATH;		/* Reached but a file */
 			}
@@ -2742,14 +2797,14 @@ FRESULT f_getcwd (
 			if (res != FR_OK) break;
 			res = dir_read(&dj);
 			if (res != FR_OK) break;
-			dj.sclust = LD_CLUST(dj.dir);	/* Goto parent dir */
+			dj.sclust = ld_clust(dj.fs, dj.dir);	/* Goto parent dir */
 			res = dir_sdi(&dj, 0);
 			if (res != FR_OK) break;
 			do {							/* Find the entry links to the child dir */
 				res = dir_read(&dj);
 				if (res != FR_OK) break;
-				if (ccl == LD_CLUST(dj.dir)) break;	/* Found the entry */
-				res = dir_next(&dj, 0);
+				if (ccl == ld_clust(dj.fs, dj.dir)) break;	/* Found the entry */
+				res = dir_next(&dj, 0);	
 			} while (res == FR_OK);
 			if (res == FR_NO_FILE) res = FR_INT_ERR;/* It cannot be 'not found'. */
 			if (res != FR_OK) break;
@@ -2803,7 +2858,7 @@ FRESULT f_lseek (
 	FRESULT res;
 
 
-	res = validate(fp->fs, fp->id);		/* Check validity of the object */
+	res = validate(fp);					/* Check validity of the object */
 	if (res != FR_OK) LEAVE_FF(fp->fs, res);
 	if (fp->flag & FA__ERROR)			/* Check abort flag */
 		LEAVE_FF(fp->fs, FR_INT_ERR);
@@ -2959,10 +3014,14 @@ FRESULT f_opendir (
 )
 {
 	FRESULT res;
+	FATFS *fs;
 	DEF_NAMEBUF;
 
 
+	if (!dj) return FR_INVALID_OBJECT;
+
 	res = chk_mounted(&path, &dj->fs, 0);
+	fs = dj->fs;
 	if (res == FR_OK) {
 		INIT_BUF(*dj);
 		res = follow_path(dj, path);			/* Follow the path to the directory */
@@ -2970,20 +3029,23 @@ FRESULT f_opendir (
 		if (res == FR_OK) {						/* Follow completed */
 			if (dj->dir) {						/* It is not the root dir */
 				if (dj->dir[DIR_Attr] & AM_DIR) {	/* The object is a directory */
-					dj->sclust = LD_CLUST(dj->dir);
+					dj->sclust = ld_clust(fs, dj->dir);
 				} else {						/* The object is not a directory */
 					res = FR_NO_PATH;
 				}
 			}
 			if (res == FR_OK) {
-				dj->id = dj->fs->id;
+				dj->id = fs->id;
 				res = dir_sdi(dj, 0);			/* Rewind dir */
 			}
 		}
 		if (res == FR_NO_FILE) res = FR_NO_PATH;
+		if (res != FR_OK) dj->fs = 0;			/* Invalidate the dir object if function failed */
+	} else {
+		dj->fs = 0;
 	}
 
-	LEAVE_FF(dj->fs, res);
+	LEAVE_FF(fs, res);
 }
 
 
@@ -3002,7 +3064,7 @@ FRESULT f_readdir (
 	DEF_NAMEBUF;
 
 
-	res = validate(dj->fs, dj->id);			/* Check validity of the object */
+	res = validate(dj);						/* Check validity of the object */
 	if (res == FR_OK) {
 		if (!fno) {
 			res = dir_sdi(dj, 0);			/* Rewind the directory object */
@@ -3075,6 +3137,7 @@ FRESULT f_getfree (
 )
 {
 	FRESULT res;
+	FATFS *fs;
 	DWORD n, clst, sect, stat;
 	UINT i;
 	BYTE fat, *p;
@@ -3082,32 +3145,33 @@ FRESULT f_getfree (
 
 	/* Get drive number */
 	res = chk_mounted(&path, fatfs, 0);
+	fs = *fatfs;
 	if (res == FR_OK) {
 		/* If free_clust is valid, return it without full cluster scan */
-		if ((*fatfs)->free_clust <= (*fatfs)->n_fatent - 2) {
-			*nclst = (*fatfs)->free_clust;
+		if (fs->free_clust <= fs->n_fatent - 2) {
+			*nclst = fs->free_clust;
 		} else {
 			/* Get number of free clusters */
-			fat = (*fatfs)->fs_type;
+			fat = fs->fs_type;
 			n = 0;
 			if (fat == FS_FAT12) {
 				clst = 2;
 				do {
-					stat = get_fat(*fatfs, clst);
+					stat = get_fat(fs, clst);
 					if (stat == 0xFFFFFFFF) { res = FR_DISK_ERR; break; }
 					if (stat == 1) { res = FR_INT_ERR; break; }
 					if (stat == 0) n++;
-				} while (++clst < (*fatfs)->n_fatent);
+				} while (++clst < fs->n_fatent);
 			} else {
-				clst = (*fatfs)->n_fatent;
-				sect = (*fatfs)->fatbase;
+				clst = fs->n_fatent;
+				sect = fs->fatbase;
 				i = 0; p = 0;
 				do {
 					if (!i) {
-						res = move_window(*fatfs, sect++);
+						res = move_window(fs, sect++);
 						if (res != FR_OK) break;
-						p = (*fatfs)->win;
-						i = SS(*fatfs);
+						p = fs->win;
+						i = SS(fs);
 					}
 					if (fat == FS_FAT16) {
 						if (LD_WORD(p) == 0) n++;
@@ -3118,12 +3182,12 @@ FRESULT f_getfree (
 					}
 				} while (--clst);
 			}
-			(*fatfs)->free_clust = n;
-			if (fat == FS_FAT32) (*fatfs)->fsi_flag = 1;
+			fs->free_clust = n;
+			if (fat == FS_FAT32) fs->fsi_flag = 1;
 			*nclst = n;
 		}
 	}
-	LEAVE_FF(*fatfs, res);
+	LEAVE_FF(fs, res);
 }
 
 
@@ -3141,7 +3205,9 @@ FRESULT f_truncate (
 	DWORD ncl;
 
 
-	res = validate(fp->fs, fp->id);		/* Check validity of the object */
+	if (!fp) return FR_INVALID_OBJECT;
+
+	res = validate(fp);						/* Check validity of the object */
 	if (res == FR_OK) {
 		if (fp->flag & FA__ERROR) {			/* Check abort flag */
 			res = FR_INT_ERR;
@@ -3198,7 +3264,7 @@ FRESULT f_unlink (
 		res = follow_path(&dj, path);		/* Follow the file path */
 		if (_FS_RPATH && res == FR_OK && (dj.fn[NS] & NS_DOT))
 			res = FR_INVALID_NAME;			/* Cannot remove dot entry */
-#if _FS_SHARE
+#if _FS_LOCK
 		if (res == FR_OK) res = chk_lock(&dj, 2);	/* Cannot remove open file */
 #endif
 		if (res == FR_OK) {					/* The object is accessible */
@@ -3209,19 +3275,19 @@ FRESULT f_unlink (
 				if (dir[DIR_Attr] & AM_RDO)
 					res = FR_DENIED;		/* Cannot remove R/O object */
 			}
-			dclst = LD_CLUST(dir);
+			dclst = ld_clust(dj.fs, dir);
 			if (res == FR_OK && (dir[DIR_Attr] & AM_DIR)) {	/* Is it a sub-dir? */
 				if (dclst < 2) {
 					res = FR_INT_ERR;
 				} else {
-					mem_cpy(&sdj, &dj, sizeof(DIR));	/* Check if the sub-dir is empty or not */
+					mem_cpy(&sdj, &dj, sizeof (DIR));	/* Check if the sub-dir is empty or not */
 					sdj.sclust = dclst;
 					res = dir_sdi(&sdj, 2);		/* Exclude dot entries */
 					if (res == FR_OK) {
 						res = dir_read(&sdj);
-						if (res == FR_OK			/* Not empty dir */
+						if (res == FR_OK		/* Not empty dir */
 #if _FS_RPATH
-						|| dclst == sdj.fs->cdir	/* Current dir */
+						|| dclst == dj.fs->cdir	/* Current dir */
 #endif
 						) res = FR_DENIED;
 						if (res == FR_NO_FILE) res = FR_OK;	/* Empty */
@@ -3283,12 +3349,12 @@ FRESULT f_mkdir (
 				dir[DIR_Name] = '.';
 				dir[DIR_Attr] = AM_DIR;
 				ST_DWORD(dir+DIR_WrtTime, tim);
-				ST_CLUST(dir, dcl);
+				st_clust(dir, dcl);
 				mem_cpy(dir+SZ_DIR, dir, SZ_DIR); 	/* Create ".." entry */
 				dir[33] = '.'; pcl = dj.sclust;
 				if (dj.fs->fs_type == FS_FAT32 && pcl == dj.fs->dirbase)
 					pcl = 0;
-				ST_CLUST(dir+SZ_DIR, pcl);
+				st_clust(dir+SZ_DIR, pcl);
 				for (n = dj.fs->csize; n; n--) {	/* Write dot entries and clear following sectors */
 					dj.fs->winsect = dsc++;
 					dj.fs->wflag = 1;
@@ -3304,7 +3370,7 @@ FRESULT f_mkdir (
 				dir = dj.dir;
 				dir[DIR_Attr] = AM_DIR;				/* Attribute */
 				ST_DWORD(dir+DIR_WrtTime, tim);		/* Created time */
-				ST_CLUST(dir, dcl);					/* Table start cluster */
+				st_clust(dir, dcl);					/* Table start cluster */
 				dj.fs->wflag = 1;
 				res = sync(dj.fs);
 			}
@@ -3361,7 +3427,7 @@ FRESULT f_chmod (
 
 
 /*-----------------------------------------------------------------------*/
-/* Change Time-stamp                                                      */
+/* Change Timestamp                                                      */
 /*-----------------------------------------------------------------------*/
 
 FRESULT f_utime (
@@ -3424,7 +3490,7 @@ FRESULT f_rename (
 		res = follow_path(&djo, path_old);		/* Check old object */
 		if (_FS_RPATH && res == FR_OK && (djo.fn[NS] & NS_DOT))
 			res = FR_INVALID_NAME;
-#if _FS_SHARE
+#if _FS_LOCK
 		if (res == FR_OK) res = chk_lock(&djo, 2);
 #endif
 		if (res == FR_OK) {						/* Old object is found */
@@ -3432,11 +3498,11 @@ FRESULT f_rename (
 				res = FR_NO_FILE;
 			} else {
 				mem_cpy(buf, djo.dir+DIR_Attr, 21);		/* Save the object information except for name */
-				mem_cpy(&djn, &djo, sizeof(DIR));		/* Check new object */
+				mem_cpy(&djn, &djo, sizeof (DIR));		/* Check new object */
 				res = follow_path(&djn, path_new);
 				if (res == FR_OK) res = FR_EXIST;		/* The new object name is already existing */
 				if (res == FR_NO_FILE) { 				/* Is it a valid path and no name collision? */
-/* Start critical section that any interruption or error can cause cross-link */
+/* Start critical section that an interruption or error can cause cross-link */
 					res = dir_register(&djn);			/* Register the new entry */
 					if (res == FR_OK) {
 						dir = djn.dir;					/* Copy object information except for name */
@@ -3444,16 +3510,16 @@ FRESULT f_rename (
 						dir[DIR_Attr] = buf[0] | AM_ARC;
 						djo.fs->wflag = 1;
 						if (djo.sclust != djn.sclust && (dir[DIR_Attr] & AM_DIR)) {		/* Update .. entry in the directory if needed */
-							dw = clust2sect(djn.fs, LD_CLUST(dir));
+							dw = clust2sect(djo.fs, ld_clust(djo.fs, dir));
 							if (!dw) {
 								res = FR_INT_ERR;
 							} else {
-								res = move_window(djn.fs, dw);
-								dir = djn.fs->win+SZ_DIR;	/* .. entry */
+								res = move_window(djo.fs, dw);
+								dir = djo.fs->win+SZ_DIR;	/* .. entry */
 								if (res == FR_OK && dir[1] == '.') {
-									dw = (djn.fs->fs_type == FS_FAT32 && djn.sclust == djn.fs->dirbase) ? 0 : djn.sclust;
-									ST_CLUST(dir, dw);
-									djn.fs->wflag = 1;
+									dw = (djo.fs->fs_type == FS_FAT32 && djn.sclust == djo.fs->dirbase) ? 0 : djn.sclust;
+									st_clust(dir, dw);
+									djo.fs->wflag = 1;
 								}
 							}
 						}
@@ -3497,9 +3563,11 @@ FRESULT f_forward (
 	BYTE csect;
 
 
-	*bf = 0;	/* Initialize byte counter */
+	*bf = 0;	/* Clear transfer byte counter */
+
+	if (!fp) return FR_INVALID_OBJECT;
 
-	res = validate(fp->fs, fp->id);					/* Check validity of the object */
+	res = validate(fp);								/* Check validity of the object */
 	if (res != FR_OK) LEAVE_FF(fp->fs, res);
 	if (fp->flag & FA__ERROR)						/* Check error flag */
 		LEAVE_FF(fp->fs, FR_INT_ERR);
@@ -3555,10 +3623,10 @@ FRESULT f_mkfs (
 {
 	static const WORD vst[] = { 1024,   512,  256,  128,   64,    32,   16,    8,    4,    2,   0};
 	static const WORD cst[] = {32768, 16384, 8192, 4096, 2048, 16384, 8192, 4096, 2048, 1024, 512};
-	BYTE fmt, md, *tbl;
+	BYTE fmt, md, sys, *tbl, pdrv, part;
 	DWORD n_clst, vs, n, wsect;
 	UINT i;
-	DWORD b_vol, b_fat, b_dir, b_data;	/* Offset (LBA) */
+	DWORD b_vol, b_fat, b_dir, b_data;	/* LBA */
 	DWORD n_vol, n_rsv, n_fat, n_dir;	/* Size */
 	FATFS *fs;
 	DSTATUS stat;
@@ -3566,25 +3634,39 @@ FRESULT f_mkfs (
 
 	/* Check mounted drive and clear work area */
 	if (drv >= _VOLUMES) return FR_INVALID_DRIVE;
+	if (sfd > 1) return FR_INVALID_PARAMETER;
+	if (au & (au - 1)) return FR_INVALID_PARAMETER;
 	fs = FatFs[drv];
 	if (!fs) return FR_NOT_ENABLED;
 	fs->fs_type = 0;
-	drv = LD2PD(drv);
+	pdrv = LD2PD(drv);	/* Physical drive */
+	part = LD2PT(drv);	/* Partition (0:auto detect, 1-4:get from partition table)*/
 
 	/* Get disk statics */
-	stat = disk_initialize(drv);
+	stat = disk_initialize(pdrv);
 	if (stat & STA_NOINIT) return FR_NOT_READY;
 	if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
 #if _MAX_SS != 512					/* Get disk sector size */
-	if (disk_ioctl(drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK)
+	if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK || SS(fs) > _MAX_SS)
 		return FR_DISK_ERR;
 #endif
-	if (disk_ioctl(drv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128)
-		return FR_DISK_ERR;
-	b_vol = (sfd) ? 0 : 63;	/* Volume start sector */
-	n_vol -= b_vol;
-	if (au & (au - 1)) au = 0;	/* Check validity of the AU size */
-	if (!au) {					/* AU auto selection */
+	if (_MULTI_PARTITION && part) {
+		/* Get partition information from partition table in the MBR */
+		if (disk_read(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR;
+		if (LD_WORD(fs->win+BS_55AA) != 0xAA55) return FR_MKFS_ABORTED;
+		tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE];
+		if (!tbl[4]) return FR_MKFS_ABORTED;	/* No partition? */
+		b_vol = LD_DWORD(tbl+8);	/* Volume start sector */
+		n_vol = LD_DWORD(tbl+12);	/* Volume size */
+	} else {
+		/* Create a partition in this function */
+		if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &n_vol) != RES_OK || n_vol < 128)
+			return FR_DISK_ERR;
+		b_vol = (sfd) ? 0 : 63;		/* Volume start sector */
+		n_vol -= b_vol;				/* Volume size */
+	}
+
+	if (!au) {				/* AU auto selection */
 		vs = n_vol / (2000 / (SS(fs) / 512));
 		for (i = 0; vs < vst[i]; i++) ;
 		au = cst[i];
@@ -3593,7 +3675,7 @@ FRESULT f_mkfs (
 	if (au == 0) au = 1;
 	if (au > 128) au = 128;
 
-	/* Pre-compute number of clusters and FAT syb-type */
+	/* Pre-compute number of clusters and FAT sub-type */
 	n_clst = n_vol / au;
 	fmt = FS_FAT12;
 	if (n_clst >= MIN_FAT16) fmt = FS_FAT16;
@@ -3613,10 +3695,10 @@ FRESULT f_mkfs (
 	b_fat = b_vol + n_rsv;				/* FAT area start sector */
 	b_dir = b_fat + n_fat * N_FATS;		/* Directory area start sector */
 	b_data = b_dir + n_dir;				/* Data area start sector */
-	if (n_vol < b_data + au) return FR_MKFS_ABORTED;	/* Too small volume */
+	if (n_vol < b_data + au - b_vol) return FR_MKFS_ABORTED;	/* Too small volume */
 
 	/* Align data start sector to erase block boundary (for flash memory media) */
-	if (disk_ioctl(drv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1;
+	if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &n) != RES_OK || !n || n > 32768) n = 1;
 	n = (b_data + n - 1) & ~(n - 1);	/* Next nearest erase block from current data start */
 	n = (n - b_data) / N_FATS;
 	if (fmt == FS_FAT32) {		/* FAT32: Move FAT offset */
@@ -3632,36 +3714,42 @@ FRESULT f_mkfs (
 		|| (fmt == FS_FAT32 && n_clst < MIN_FAT32))
 		return FR_MKFS_ABORTED;
 
-	/* Create partition table if required */
-	if (sfd) {	/* No partition table (SFD) */
-		md = 0xF0;
-	} else {	/* With partition table (FDISK) */
-		DWORD n_disk = b_vol + n_vol;
-
-		mem_set(fs->win, 0, SS(fs));
-		tbl = fs->win+MBR_Table;
-		ST_DWORD(tbl, 0x00010180);			/* Partition start in CHS */
-		if (n_disk < 63UL * 255 * 1024) {	/* Partition end in CHS */
-			n_disk = n_disk / 63 / 255;
-			tbl[7] = (BYTE)n_disk;
-			tbl[6] = (BYTE)((n_disk >> 2) | 63);
-		} else {
-			ST_WORD(&tbl[6], 0xFFFF);	/* CHS saturated */
-		}
-		tbl[5] = 254;
-		if (fmt != FS_FAT32)				/* System ID */
-			tbl[4] = (n_vol < 0x10000) ? 0x04 : 0x06;
-		else
-			tbl[4] = 0x0c;
-		ST_DWORD(tbl+8, 63);				/* Partition start in LBA */
-		ST_DWORD(tbl+12, n_vol);			/* Partition size in LBA */
-		ST_WORD(fs->win+BS_55AA, 0xAA55);	/* MBR signature */
-		if (disk_write(drv, fs->win, 0, 1) != RES_OK)	/* Put the MBR into first physical sector */
-			return FR_DISK_ERR;
+	switch (fmt) {	/* Determine system ID for partition table */
+	case FS_FAT12:	sys = 0x01; break;
+	case FS_FAT16:	sys = (n_vol < 0x10000) ? 0x04 : 0x06; break;
+	default: 		sys = 0x0C;
+	}
+
+	if (_MULTI_PARTITION && part) {
+		/* Update system ID in the partition table */
+		tbl = &fs->win[MBR_Table + (part - 1) * SZ_PTE];
+		tbl[4] = sys;
+		if (disk_write(pdrv, fs->win, 0, 1) != RES_OK) return FR_DISK_ERR;
 		md = 0xF8;
+	} else {
+		if (sfd) {	/* No partition table (SFD) */
+			md = 0xF0;
+		} else {	/* Create partition table (FDISK) */
+			mem_set(fs->win, 0, SS(fs));
+			tbl = fs->win+MBR_Table;	/* Create partition table for single partition in the drive */
+			tbl[1] = 1;						/* Partition start head */
+			tbl[2] = 1;						/* Partition start sector */
+			tbl[3] = 0;						/* Partition start cylinder */
+			tbl[4] = sys;					/* System type */
+			tbl[5] = 254;					/* Partition end head */
+			n = (b_vol + n_vol) / 63 / 255;
+			tbl[6] = (BYTE)((n >> 2) | 63);	/* Partition end sector */
+			tbl[7] = (BYTE)n;				/* End cylinder */
+			ST_DWORD(tbl+8, 63);			/* Partition start in LBA */
+			ST_DWORD(tbl+12, n_vol);		/* Partition size in LBA */
+			ST_WORD(fs->win+BS_55AA, 0xAA55);	/* MBR signature */
+			if (disk_write(pdrv, fs->win, 0, 1) != RES_OK)	/* Write it to the MBR sector */
+				return FR_DISK_ERR;
+			md = 0xF8;
+		}
 	}
 
-	/* Create volume boot record */
+	/* Create BPB in the VBR */
 	tbl = fs->win;							/* Clear sector */
 	mem_set(tbl, 0, SS(fs));
 	mem_cpy(tbl, "\xEB\xFE\x90" "MSDOS5.0", 11);/* Boot jump code, OEM name */
@@ -3699,10 +3787,10 @@ FRESULT f_mkfs (
 		mem_cpy(tbl+BS_VolLab, "NO NAME    " "FAT     ", 19);	/* Volume label, FAT signature */
 	}
 	ST_WORD(tbl+BS_55AA, 0xAA55);			/* Signature (Offset is fixed here regardless of sector size) */
-	if (disk_write(drv, tbl, b_vol, 1) != RES_OK)	/* Write VBR */
+	if (disk_write(pdrv, tbl, b_vol, 1) != RES_OK)	/* Write it to the VBR sector */
 		return FR_DISK_ERR;
 	if (fmt == FS_FAT32)							/* Write backup VBR if needed (VBR+6) */
-		disk_write(drv, tbl, b_vol + 6, 1);
+		disk_write(pdrv, tbl, b_vol + 6, 1);
 
 	/* Initialize FAT area */
 	wsect = b_fat;
@@ -3718,11 +3806,11 @@ FRESULT f_mkfs (
 			ST_DWORD(tbl+4, 0xFFFFFFFF);
 			ST_DWORD(tbl+8, 0x0FFFFFFF);	/* Reserve cluster #2 for root dir */
 		}
-		if (disk_write(drv, tbl, wsect++, 1) != RES_OK)
+		if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
 			return FR_DISK_ERR;
 		mem_set(tbl, 0, SS(fs));			/* Fill following FAT entries with zero */
 		for (n = 1; n < n_fat; n++) {		/* This loop may take a time on FAT32 volume due to many single sector writes */
-			if (disk_write(drv, tbl, wsect++, 1) != RES_OK)
+			if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
 				return FR_DISK_ERR;
 		}
 	}
@@ -3730,7 +3818,7 @@ FRESULT f_mkfs (
 	/* Initialize root directory */
 	i = (fmt == FS_FAT32) ? au : n_dir;
 	do {
-		if (disk_write(drv, tbl, wsect++, 1) != RES_OK)
+		if (disk_write(pdrv, tbl, wsect++, 1) != RES_OK)
 			return FR_DISK_ERR;
 	} while (--i);
 
@@ -3739,7 +3827,7 @@ FRESULT f_mkfs (
 		DWORD eb[2];
 
 		eb[0] = wsect; eb[1] = wsect + (n_clst - ((fmt == FS_FAT32) ? 1 : 0)) * au - 1;
-		disk_ioctl(drv, CTRL_ERASE_SECTOR, eb);
+		disk_ioctl(pdrv, CTRL_ERASE_SECTOR, eb);
 	}
 #endif
 
@@ -3750,13 +3838,82 @@ FRESULT f_mkfs (
 		ST_DWORD(tbl+FSI_Free_Count, n_clst - 1);	/* Number of free clusters */
 		ST_DWORD(tbl+FSI_Nxt_Free, 2);				/* Last allocated cluster# */
 		ST_WORD(tbl+BS_55AA, 0xAA55);
-		disk_write(drv, tbl, b_vol + 1, 1);	/* Write original (VBR+1) */
-		disk_write(drv, tbl, b_vol + 7, 1);	/* Write backup (VBR+7) */
+		disk_write(pdrv, tbl, b_vol + 1, 1);	/* Write original (VBR+1) */
+		disk_write(pdrv, tbl, b_vol + 7, 1);	/* Write backup (VBR+7) */
+	}
+
+	return (disk_ioctl(pdrv, CTRL_SYNC, 0) == RES_OK) ? FR_OK : FR_DISK_ERR;
+}
+
+
+#if _MULTI_PARTITION == 2
+/*-----------------------------------------------------------------------*/
+/* Divide Physical Drive                                                 */
+/*-----------------------------------------------------------------------*/
+
+FRESULT f_fdisk (
+	BYTE pdrv,			/* Physical drive number */
+	const DWORD szt[],	/* Pointer to the size table for each partitions */
+	void* work			/* Pointer to the working buffer */
+)
+{
+	UINT i, n, sz_cyl, tot_cyl, b_cyl, e_cyl, p_cyl;
+	BYTE s_hd, e_hd, *p, *buf = (BYTE*)work;
+	DSTATUS stat;
+	DWORD sz_disk, sz_part, s_part;
+
+
+	stat = disk_initialize(pdrv);
+	if (stat & STA_NOINIT) return FR_NOT_READY;
+	if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
+	if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR;
+
+	/* Determine CHS in the table regardless of the drive geometry */
+	for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ;
+	if (n == 256) n--;
+	e_hd = n - 1;
+	sz_cyl = 63 * n;
+	tot_cyl = sz_disk / sz_cyl;
+
+	/* Create partition table */
+	mem_set(buf, 0, _MAX_SS);
+	p = buf + MBR_Table; b_cyl = 0;
+	for (i = 0; i < 4; i++, p += SZ_PTE) {
+		p_cyl = (szt[i] <= 100) ? (DWORD)tot_cyl * szt[i] / 100 : szt[i] / sz_cyl;
+		if (!p_cyl) continue;
+		s_part = (DWORD)sz_cyl * b_cyl;
+		sz_part = (DWORD)sz_cyl * p_cyl;
+		if (i == 0) {	/* Exclude first track of cylinder 0 */
+			s_hd = 1;
+			s_part += 63; sz_part -= 63;
+		} else {
+			s_hd = 0;
+		}
+		e_cyl = b_cyl + p_cyl - 1;
+		if (e_cyl >= tot_cyl) return FR_INVALID_PARAMETER;
+
+		/* Set partition table */
+		p[1] = s_hd;						/* Start head */
+		p[2] = (BYTE)((b_cyl >> 2) + 1);	/* Start sector */
+		p[3] = (BYTE)b_cyl;					/* Start cylinder */
+		p[4] = 0x06;						/* System type (temporary setting) */
+		p[5] = e_hd;						/* End head */
+		p[6] = (BYTE)((e_cyl >> 2) + 63);	/* End sector */
+		p[7] = (BYTE)e_cyl;					/* End cylinder */
+		ST_DWORD(p + 8, s_part);			/* Start sector in LBA */
+		ST_DWORD(p + 12, sz_part);			/* Partition size */
+
+		/* Next partition */
+		b_cyl += p_cyl;
 	}
+	ST_WORD(p, 0xAA55);
 
-	return (disk_ioctl(drv, CTRL_SYNC, (void*)0) == RES_OK) ? FR_OK : FR_DISK_ERR;
+	/* Write it to the MBR */
+	return (disk_write(pdrv, buf, 0, 1) || disk_ioctl(pdrv, CTRL_SYNC, 0)) ? FR_DISK_ERR : FR_OK;
 }
 
+
+#endif /* _MULTI_PARTITION == 2 */
 #endif /* _USE_MKFS && !_FS_READONLY */
 
 
@@ -3894,7 +4051,7 @@ int f_printf (
 	UINT i, j, w;
 	ULONG v;
 	TCHAR c, d, s[16], *p;
-	int res, cc;
+	int res, chc, cc;
 
 
 	va_start(arp, str);
@@ -3930,11 +4087,13 @@ int f_printf (
 		case 'S' :					/* String */
 			p = va_arg(arp, TCHAR*);
 			for (j = 0; p[j]; j++) ;
-			res = 0;
-			while (!(f & 2) && j++ < w) res += (cc = f_putc(' ', fil));
-			res += (cc = f_puts(p, fil));
-			while (j++ < w) res += (cc = f_putc(' ', fil));
-			if (cc != EOF) cc = res;
+			chc = 0;
+			if (!(f & 2)) {
+				while (j++ < w) chc += (cc = f_putc(' ', fil));
+			}
+			chc += (cc = f_puts(p, fil));
+			while (j++ < w) chc += (cc = f_putc(' ', fil));
+			if (cc != EOF) cc = chc;
 			continue;
 		case 'C' :					/* Character */
 			cc = f_putc((TCHAR)va_arg(arp, int), fil); continue;
@@ -3945,14 +4104,14 @@ int f_printf (
 		case 'D' :					/* Signed decimal */
 		case 'U' :					/* Unsigned decimal */
 			r = 10; break;
-		case 'X' :					/* Hexadecimal */
+		case 'X' :					/* Hexdecimal */
 			r = 16; break;
-		default:					/* Unknown type (passthrough) */
+		default:					/* Unknown type (pass-through) */
 			cc = f_putc(c, fil); continue;
 		}
 
 		/* Get an argument and put it in numeral */
-		v = (f & 4) ? va_arg(arp, long) : ((d == 'D') ? (long)va_arg(arp, int) : va_arg(arp, unsigned int));
+		v = (f & 4) ? (ULONG)va_arg(arp, long) : ((d == 'D') ? (ULONG)(long)va_arg(arp, int) : (ULONG)va_arg(arp, unsigned int));
 		if (d == 'D' && (v & 0x80000000)) {
 			v = 0 - v;
 			f |= 8;
@@ -3962,7 +4121,7 @@ int f_printf (
 			d = (TCHAR)(v % r); v /= r;
 			if (d > 9) d += (c == 'x') ? 0x27 : 0x07;
 			s[i++] = d + '0';
-		} while (v && i < sizeof(s) / sizeof(s[0]));
+		} while (v && i < sizeof s / sizeof s[0]);
 		if (f & 8) s[i++] = '-';
 		j = i; d = (f & 1) ? '0' : ' ';
 		res = 0;
@@ -3978,4 +4137,3 @@ int f_printf (
 
 #endif /* !_FS_READONLY */
 #endif /* _USE_STRFUNC */
-
diff --git a/Projects/Webserver/Lib/FATFs/ff.h b/Projects/Webserver/Lib/FATFs/ff.h
index 6a4107cdf..627cbaabe 100644
--- a/Projects/Webserver/Lib/FATFs/ff.h
+++ b/Projects/Webserver/Lib/FATFs/ff.h
@@ -1,11 +1,11 @@
 /*---------------------------------------------------------------------------/
-/  FatFs - FAT file system module include file  R0.08b    (C)ChaN, 2011
+/  FatFs - FAT file system module include file  R0.09a    (C)ChaN, 2012
 /----------------------------------------------------------------------------/
 / FatFs module is a generic FAT file system module for small embedded systems.
 / This is a free software that opened for education, research and commercial
 / developments under license policy of following terms.
 /
-/  Copyright (C) 2011, ChaN, all right reserved.
+/  Copyright (C) 2012, ChaN, all right reserved.
 /
 / * The FatFs module is a free software and there is NO WARRANTY.
 / * No restriction on use. You can use, modify and redistribute it for
@@ -15,7 +15,7 @@
 /----------------------------------------------------------------------------*/
 
 #ifndef _FATFS
-#define _FATFS	8237	/* Revision ID */
+#define _FATFS	4004	/* Revision ID */
 
 #ifdef __cplusplus
 extern "C" {
@@ -33,17 +33,17 @@ extern "C" {
 /* Definitions of volume management */
 
 #if _MULTI_PARTITION		/* Multiple partition configuration */
-#define LD2PD(vol) (VolToPart[vol].pd)	/* Get physical drive# */
-#define LD2PT(vol) (VolToPart[vol].pt)	/* Get partition# */
 typedef struct {
-	BYTE pd;	/* Physical drive# */
-	BYTE pt;	/* Partition # (0-3) */
+	BYTE pd;	/* Physical drive number */
+	BYTE pt;	/* Partition: 0:Auto detect, 1-4:Forced partition) */
 } PARTITION;
-extern const PARTITION VolToPart[];	/* Volume - Physical location resolution table */
+extern PARTITION VolToPart[];	/* Volume - Partition resolution table */
+#define LD2PD(vol) (VolToPart[vol].pd)	/* Get physical drive number */
+#define LD2PT(vol) (VolToPart[vol].pt)	/* Get partition index */
 
-#else						/* Single partition configuration */
-#define LD2PD(vol) (vol)	/* Logical drive# is bound to the same physical drive# */
-#define LD2PT(vol) 0		/* Always mounts the 1st partition */
+#else							/* Single partition configuration */
+#define LD2PD(vol) (BYTE)(vol)	/* Each logical drive is bound to the same physical drive number */
+#define LD2PT(vol) 0			/* Always mounts the 1st partition or in SFD */
 
 #endif
 
@@ -84,7 +84,7 @@ typedef struct {
 	WORD	id;				/* File system mount ID */
 	WORD	n_rootdir;		/* Number of root directory entries (FAT12/16) */
 #if _MAX_SS != 512
-	WORD	ssize;			/* Bytes per sector (512,1024,2048,4096) */
+	WORD	ssize;			/* Bytes per sector (512, 1024, 2048 or 4096) */
 #endif
 #if _FS_REENTRANT
 	_SYNC_t	sobj;			/* Identifier of sync object */
@@ -111,24 +111,24 @@ typedef struct {
 /* File object structure (FIL) */
 
 typedef struct {
-	FATFS*	fs;				/* Pointer to the owner file system object */
-	WORD	id;				/* Owner file system mount ID */
+	FATFS*	fs;				/* Pointer to the related file system object */
+	WORD	id;				/* File system mount ID of the related file system object */
 	BYTE	flag;			/* File status flags */
 	BYTE	pad1;
-	DWORD	fptr;			/* File read/write pointer (0 on file open) */
+	DWORD	fptr;			/* File read/write pointer (0ed on file open) */
 	DWORD	fsize;			/* File size */
-	DWORD	sclust;			/* File start cluster (0 when fsize==0) */
-	DWORD	clust;			/* Current cluster */
-	DWORD	dsect;			/* Current data sector */
+	DWORD	sclust;			/* File data start cluster (0:no data cluster, always 0 when fsize is 0) */
+	DWORD	clust;			/* Current cluster of fpter */
+	DWORD	dsect;			/* Current data sector of fpter */
 #if !_FS_READONLY
 	DWORD	dir_sect;		/* Sector containing the directory entry */
-	BYTE*	dir_ptr;		/* Ponter to the directory entry in the window */
+	BYTE*	dir_ptr;		/* Pointer to the directory entry in the window */
 #endif
 #if _USE_FASTSEEK
 	DWORD*	cltbl;			/* Pointer to the cluster link map table (null on file open) */
 #endif
-#if _FS_SHARE
-	UINT	lockid;			/* File lock ID (index of file semaphore table) */
+#if _FS_LOCK
+	UINT	lockid;			/* File lock ID (index of file semaphore table Files[]) */
 #endif
 #if !_FS_TINY
 	BYTE	buf[_MAX_SS];	/* File data read/write buffer */
@@ -188,12 +188,13 @@ typedef enum {
 	FR_WRITE_PROTECTED,		/* (10) The physical drive is write protected */
 	FR_INVALID_DRIVE,		/* (11) The logical drive number is invalid */
 	FR_NOT_ENABLED,			/* (12) The volume has no work area */
-	FR_NO_FILESYSTEM,		/* (13) There is no valid FAT volume on the physical drive */
+	FR_NO_FILESYSTEM,		/* (13) There is no valid FAT volume */
 	FR_MKFS_ABORTED,		/* (14) The f_mkfs() aborted due to any parameter error */
 	FR_TIMEOUT,				/* (15) Could not get a grant to access the volume within defined period */
 	FR_LOCKED,				/* (16) The operation is rejected according to the file sharing policy */
 	FR_NOT_ENOUGH_CORE,		/* (17) LFN working buffer could not be allocated */
-	FR_TOO_MANY_OPEN_FILES	/* (18) Number of open files > _FS_SHARE */
+	FR_TOO_MANY_OPEN_FILES,	/* (18) Number of open files > _FS_SHARE */
+	FR_INVALID_PARAMETER	/* (19) Given parameter is invalid */
 } FRESULT;
 
 
@@ -216,27 +217,28 @@ FRESULT f_sync (FIL*);								/* Flush cached data of a writing file */
 FRESULT f_unlink (const TCHAR*);					/* Delete an existing file or directory */
 FRESULT	f_mkdir (const TCHAR*);						/* Create a new directory */
 FRESULT f_chmod (const TCHAR*, BYTE, BYTE);			/* Change attribute of the file/dir */
-FRESULT f_utime (const TCHAR*, const FILINFO*);		/* Change time-stamp of the file/dir */
+FRESULT f_utime (const TCHAR*, const FILINFO*);		/* Change times-tamp of the file/dir */
 FRESULT f_rename (const TCHAR*, const TCHAR*);		/* Rename/Move a file or directory */
-FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*);	/* Forward data to the stream */
-FRESULT f_mkfs (BYTE, BYTE, UINT);					/* Create a file system on the drive */
 FRESULT f_chdrive (BYTE);							/* Change current drive */
 FRESULT f_chdir (const TCHAR*);						/* Change current directory */
 FRESULT f_getcwd (TCHAR*, UINT);					/* Get current directory */
+FRESULT f_forward (FIL*, UINT(*)(const BYTE*,UINT), UINT, UINT*);	/* Forward data to the stream */
+FRESULT f_mkfs (BYTE, BYTE, UINT);					/* Create a file system on the drive */
+FRESULT	f_fdisk (BYTE, const DWORD[], void*);		/* Divide a physical drive into some partitions */
 int f_putc (TCHAR, FIL*);							/* Put a character to the file */
 int f_puts (const TCHAR*, FIL*);					/* Put a string to the file */
 int f_printf (FIL*, const TCHAR*, ...);				/* Put a formatted string to the file */
 TCHAR* f_gets (TCHAR*, int, FIL*);					/* Get a string from the file */
 
-#ifndef EOF
-#define EOF (-1)
-#endif
-
 #define f_eof(fp) (((fp)->fptr == (fp)->fsize) ? 1 : 0)
 #define f_error(fp) (((fp)->flag & FA__ERROR) ? 1 : 0)
 #define f_tell(fp) ((fp)->fptr)
 #define f_size(fp) ((fp)->fsize)
 
+#ifndef EOF
+#define EOF (-1)
+#endif
+
 
 
 
@@ -308,7 +310,7 @@ int ff_del_syncobj (_SYNC_t);		/* Delete a sync object */
 #define AM_MASK	0x3F	/* Mask of defined bits */
 
 
-/* Fast seek function */
+/* Fast seek feature */
 #define CREATE_LINKMAP	0xFFFFFFFF
 
 
@@ -333,4 +335,3 @@ int ff_del_syncobj (_SYNC_t);		/* Delete a sync object */
 #endif
 
 #endif /* _FATFS */
-
diff --git a/Projects/Webserver/Lib/FATFs/ffconf.h b/Projects/Webserver/Lib/FATFs/ffconf.h
index 782f2bd65..243a20fa2 100644
--- a/Projects/Webserver/Lib/FATFs/ffconf.h
+++ b/Projects/Webserver/Lib/FATFs/ffconf.h
@@ -1,5 +1,5 @@
 /*---------------------------------------------------------------------------/
-/  FatFs - FAT file system module configuration file  R0.08b (C)ChaN, 2011
+/  FatFs - FAT file system module configuration file  R0.09a (C)ChaN, 2012
 /----------------------------------------------------------------------------/
 /
 / CAUTION! Do not forget to make clean the project after any changes to
@@ -7,7 +7,7 @@
 /
 /----------------------------------------------------------------------------*/
 #ifndef _FFCONF
-#define _FFCONF 8237	/* Revision ID */
+#define _FFCONF 4004	/* Revision ID */
 
 
 /*---------------------------------------------------------------------------/
@@ -36,7 +36,7 @@
 /   3: f_lseek is removed in addition to 2. */
 
 
-#define	_USE_STRFUNC	0	/* 0:Disable or 1/2:Enable */
+#define	_USE_STRFUNC	0	/* 0:Disable or 1-2:Enable */
 /* To enable string functions, set _USE_STRFUNC to 1 or 2. */
 
 
@@ -137,7 +137,7 @@
 /  and GET_SECTOR_SIZE command must be implemented to the disk_ioctl function. */
 
 
-#define	_MULTI_PARTITION	0	/* 0:Single partition or 1:Multiple partition */
+#define	_MULTI_PARTITION	0	/* 0:Single partition, 1/2:Enable multiple partition */
 /* When set to 0, each volume is bound to the same physical drive number and
 / it can mount only first primary partition. When it is set to 1, each volume
 / is tied to the partitions listed in VolToPart[]. */
@@ -181,9 +181,9 @@
 /      function must be added to the project. */
 
 
-#define	_FS_SHARE	0	/* 0:Disable or >=1:Enable */
-/* To enable file sharing feature, set _FS_SHARE to 1 or greater. The value
-   defines how many files can be opened simultaneously. */
+#define	_FS_LOCK	0	/* 0:Disable or >=1:Enable */
+/* To enable file lock control feature, set _FS_LOCK to 1 or greater.
+   The value defines how many files can be opened simultaneously. */
 
 
 #endif /* _FFCONFIG */
-- 
GitLab