diff --git a/sys/.settings/language.settings.xml b/sys/.settings/language.settings.xml
index d89350f..c34d675 100644
--- a/sys/.settings/language.settings.xml
+++ b/sys/.settings/language.settings.xml
@@ -5,7 +5,7 @@
 			
 			
 			
-			
+			
 				
 				
 			
diff --git a/sys/fs/fat/API.txt b/sys/fs/fat/API.txt
new file mode 100644
index 0000000..61fc164
--- /dev/null
+++ b/sys/fs/fat/API.txt
@@ -0,0 +1,22 @@
+File IO Lib API
+-=-=-=-=-=-=-=-=-
+
+void fl_init(void)
+
+  Called to initialize FAT IO library.
+  This should be called prior to any other functions.
+
+void fl_attach_locks(void (*lock)(void), void (*unlock)(void))
+
+  [Optional] File system thread safety locking functions.
+  For thread safe operation, you should provide lock() and unlock() functions.
+  Note that locking primitive used must support recursive locking, i.e lock() called within an already �locked� region.
+
+int fl_attach_media(fn_diskio_read rd, fn_diskio_write wr)
+
+  This function is used to attach system specific disk/media access functions.  
+  This should be done subsequent to calling fl_init() and fl_attach_locks() (if locking required).
+
+void fl_shutdown(void)
+
+  Shutdown the FAT IO library. This purges any un-saved data back to disk.
diff --git a/sys/fs/fat/COPYRIGHT.txt b/sys/fs/fat/COPYRIGHT.txt
new file mode 100644
index 0000000..4335f7f
--- /dev/null
+++ b/sys/fs/fat/COPYRIGHT.txt
@@ -0,0 +1,345 @@
+		    GNU GENERAL PUBLIC LICENSE
+		       Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.
+                       59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+			    Preamble
+
+  The licenses for most software are designed to take away your
+freedom to share and change it.  By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users.  This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it.  (Some other Free Software Foundation software is covered by
+the GNU Library General Public License instead.)  You can apply it to
+your programs, too.
+
+  When we speak of free software, we are referring to freedom, not
+price.  Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+  To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+  For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have.  You must make sure that they, too, receive or can get the
+source code.  And you must show them these terms so they know their
+rights.
+
+  We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+  Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software.  If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+  Finally, any free program is threatened constantly by software
+patents.  We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary.  To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+  The precise terms and conditions for copying, distribution and
+modification follow.
+
+
+		    GNU GENERAL PUBLIC LICENSE
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+  0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License.  The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language.  (Hereinafter, translation is included without limitation in
+the term "modification".)  Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope.  The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+  1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+  2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+    a) You must cause the modified files to carry prominent notices
+    stating that you changed the files and the date of any change.
+
+    b) You must cause any work that you distribute or publish, that in
+    whole or in part contains or is derived from the Program or any
+    part thereof, to be licensed as a whole at no charge to all third
+    parties under the terms of this License.
+
+    c) If the modified program normally reads commands interactively
+    when run, you must cause it, when started running for such
+    interactive use in the most ordinary way, to print or display an
+    announcement including an appropriate copyright notice and a
+    notice that there is no warranty (or else, saying that you provide
+    a warranty) and that users may redistribute the program under
+    these conditions, and telling the user how to view a copy of this
+    License.  (Exception: if the Program itself is interactive but
+    does not normally print such an announcement, your work based on
+    the Program is not required to print an announcement.)
+
+
+These requirements apply to the modified work as a whole.  If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works.  But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+  3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+    a) Accompany it with the complete corresponding machine-readable
+    source code, which must be distributed under the terms of Sections
+    1 and 2 above on a medium customarily used for software interchange; or,
+
+    b) Accompany it with a written offer, valid for at least three
+    years, to give any third party, for a charge no more than your
+    cost of physically performing source distribution, a complete
+    machine-readable copy of the corresponding source code, to be
+    distributed under the terms of Sections 1 and 2 above on a medium
+    customarily used for software interchange; or,
+
+    c) Accompany it with the information you received as to the offer
+    to distribute corresponding source code.  (This alternative is
+    allowed only for noncommercial distribution and only if you
+    received the program in object code or executable form with such
+    an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it.  For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable.  However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+
+  4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License.  Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+  5. You are not required to accept this License, since you have not
+signed it.  However, nothing else grants you permission to modify or
+distribute the Program or its derivative works.  These actions are
+prohibited by law if you do not accept this License.  Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+  6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions.  You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+  7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License.  If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all.  For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices.  Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+
+  8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded.  In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+  9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time.  Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number.  If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation.  If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+  10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission.  For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this.  Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+			    NO WARRANTY
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+		     END OF TERMS AND CONDITIONS
+
+
+	    How to Apply These Terms to Your New Programs
+
+  If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+  To do so, attach the following notices to the program.  It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+    
+    Copyright (C)   
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+    Gnomovision version 69, Copyright (C) year name of author
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+    This is free software, and you are welcome to redistribute it
+    under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License.  Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary.  Here is a sample; alter the names:
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+  `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+  , 1 April 1989
+  Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs.  If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library.  If this is what you want to do, use the GNU Library General
+Public License instead of this License.
diff --git a/sys/fs/fat/Configuration.txt b/sys/fs/fat/Configuration.txt
new file mode 100644
index 0000000..370f1da
--- /dev/null
+++ b/sys/fs/fat/Configuration.txt
@@ -0,0 +1,53 @@
+File IO Lib Options
+-=-=-=-=-=-=-=-=-=-
+
+See defines in fat_opts.h:
+
+FATFS_IS_LITTLE_ENDIAN 	[1/0]
+  Which endian is your system? Set to 1 for little endian, 0 for big endian.
+
+FATFS_MAX_LONG_FILENAME	[260]
+  By default, 260 characters (max LFN length). Increase this to support greater path depths.
+
+FATFS_MAX_OPEN_FILES 	
+  The more files you wish to have concurrently open, the greater this number should be.
+  This increases the number of FL_FILE file structures in the library, each of these is around 1K in size (assuming 512 byte sectors).
+
+FAT_BUFFER_SECTORS
+  Minimum is 1, more increases performance.
+  This defines how many FAT sectors can be buffered per FAT_BUFFER entry.
+
+FAT_BUFFERS
+  Minimum is 1, more increases performance.
+  This defines how many FAT buffer entries are available.
+  Memory usage is FAT_BUFFERS * FAT_BUFFER_SECTORS * FAT_SECTOR_SIZE
+
+FATFS_INC_WRITE_SUPPORT
+  Support file write functionality.
+
+FAT_SECTOR_SIZE
+  Sector size used by buffers. Most likely to be 512 bytes (standard for ATA/IDE).
+
+FAT_PRINTF
+  A define that allows the File IO library to print to console/stdout. 
+  Provide your own printf function if printf not available.
+
+FAT_CLUSTER_CACHE_ENTRIES
+  Size of cluster chain cache (can be undefined if not required).
+  Mem used = FAT_CLUSTER_CACHE_ENTRIES * 4 * 2
+  Improves access speed considerably.
+
+FATFS_INC_LFN_SUPPORT 	[1/0]
+  Enable/Disable support for long filenames.
+
+FATFS_DIR_LIST_SUPPORT 	[1/0]
+  Include support for directory listing.
+
+FATFS_INC_TIME_DATE_SUPPORT  [1/0]
+  Use time/date functions provided by time.h to update creation & modification timestamps.
+
+FATFS_INC_FORMAT_SUPPORT
+  Include support for formatting disks (FAT16 only).
+
+FAT_PRINTF_NOINC_STDIO
+  Disable use of printf & inclusion of stdio.h
diff --git a/sys/fs/fat/History.txt b/sys/fs/fat/History.txt
new file mode 100644
index 0000000..58958f4
--- /dev/null
+++ b/sys/fs/fat/History.txt
@@ -0,0 +1,24 @@
+Revision History
+-=-=-=-=-=-=-=-=-
+v2.6.11 - Fix compilation with GCC on 64-bit machines
+v2.6.10 - Added support for FAT32 format.
+V2.6.9  - Added support for time & date handling.
+V2.6.8  - Fixed error with FSINFO sector write.
+V2.6.7  - Added fgets().
+          Fixed C warnings, removed dependancy on some string.h functions.
+V2.6.6  � Massive read + write performance  improvements.
+V2.6.5  � Bug fixes for big endian systems.
+V2.6.4  � Further bug fixes and performance improvements for write operations.
+V2.6.3  � Peformance improvements, FAT16 formatting support. Various bug fixes.
+V2.6    - Basic support for FAT16 added (18-04-10).
+V2.5    - Code cleaned up. Many bugs fixed. Thread safety functions added.
+V2.x    - Write support added as well as better stdio like API.
+V1.0    - Rewrite of all code to enable multiple files to be opened and provides a 
+          better file API.
+	  Also better string matching, and generally better C code than origonal 
+          version.
+V0.1c   - Fetch_ID_Max_LBA() function added to retrieve Drive infomation and stoping 
+          the drive reads from addressing a sector that is out of range.
+V0.1b   - fopen(), fgetc(), fopenDIR() using new software stack for IDE and FAT32 
+          access.
+V0.1a   - First release (27/12/03); fopen(), fgetc() unbuffered reads.
diff --git a/sys/fs/fat/License.txt b/sys/fs/fat/License.txt
new file mode 100644
index 0000000..c7fb0cc
--- /dev/null
+++ b/sys/fs/fat/License.txt
@@ -0,0 +1,10 @@
+FAT File IO Library License
+-=-=-=-=-=-=-=-=-=-=-=-=-=-
+
+This versions license: GPL
+
+If you include GPL software in your project, you must release the source code of that project too.
+
+If you would like a version with a more permissive license for use in closed source commercial applications please contact me for details.
+
+Email: admin@ultra-embedded.com
diff --git a/sys/fs/fat/Media Access API.txt b/sys/fs/fat/Media Access API.txt
new file mode 100644
index 0000000..14ceed3
--- /dev/null
+++ b/sys/fs/fat/Media Access API.txt
@@ -0,0 +1,40 @@
+Media Access API
+-=-=-=-=-=-=-=-=-
+
+int media_read(uint32 sector, uint8 *buffer, uint32 sector_count)
+
+Params:
+	Sector: 32-bit sector number
+	Buffer: Target buffer to read n sectors of data into.
+	Sector_count: Number of sectors to read.
+
+Return: 
+	int, 1 = success, 0 = failure.
+
+Description:
+   Application/target specific disk/media read function.
+   Sector number (sectors are usually 512 byte pages) to read.
+
+Media Write API
+
+int media_write(uint32 sector, uint8 *buffer, uint32 sector_count)
+
+Params:
+	Sector: 32-bit sector number
+	Buffer: Target buffer to write n sectors of data from.
+	Sector_count: Number of sectors to write.
+
+Return: 
+	int, 1 = success, 0 = failure.
+
+Description:
+   Application/target specific disk/media write function.
+   Sector number (sectors are usually 512 byte pages) to write to.
+
+File IO Library Linkage
+   Use the following API to attach the media IO functions to the File IO library.
+
+   int fl_attach_media(fn_diskio_read rd, fn_diskio_write wr)
+
+
+
diff --git a/sys/fs/fat/example.c b/sys/fs/fat/example.c
new file mode 100644
index 0000000..340f0bd
--- /dev/null
+++ b/sys/fs/fat/example.c
@@ -0,0 +1,87 @@
+#include 
+#include "fat_filelib.h"
+
+int media_init()
+{
+    // ...
+    return 1;
+}
+
+int media_read(unsigned long sector, unsigned char *buffer, unsigned long sector_count)
+{
+    unsigned long i;
+
+    for (i=0;i
+#include "fat_defs.h"
+#include "fat_access.h"
+#include "fat_table.h"
+#include "fat_write.h"
+#include "fat_string.h"
+#include "fat_misc.h"
+
+//-----------------------------------------------------------------------------
+// fatfs_init: Load FAT Parameters
+//-----------------------------------------------------------------------------
+int fatfs_init(struct fatfs *fs)
+{
+    uint8 num_of_fats;
+    uint16 reserved_sectors;
+    uint32 FATSz;
+    uint32 root_dir_sectors;
+    uint32 total_sectors;
+    uint32 data_sectors;
+    uint32 count_of_clusters;
+    uint8 valid_partition = 0;
+
+    fs->currentsector.address = FAT32_INVALID_CLUSTER;
+    fs->currentsector.dirty = 0;
+
+    fs->next_free_cluster = 0; // Invalid
+
+    fatfs_fat_init(fs);
+
+    // Make sure we have a read function (write function is optional)
+    if (!fs->disk_io.read_media)
+        return FAT_INIT_MEDIA_ACCESS_ERROR;
+
+    // MBR: Sector 0 on the disk
+    // NOTE: Some removeable media does not have this.
+
+    // Load MBR (LBA 0) into the 512 byte buffer
+    if (!fs->disk_io.read_media(0, fs->currentsector.sector, 1))
+        return FAT_INIT_MEDIA_ACCESS_ERROR;
+
+    // Make Sure 0x55 and 0xAA are at end of sector
+    // (this should be the case regardless of the MBR or boot sector)
+    if (fs->currentsector.sector[SIGNATURE_POSITION] != 0x55 || fs->currentsector.sector[SIGNATURE_POSITION+1] != 0xAA)
+        return FAT_INIT_INVALID_SIGNATURE;
+
+    // Now check again using the access function to prove endian conversion function
+    if (GET_16BIT_WORD(fs->currentsector.sector, SIGNATURE_POSITION) != SIGNATURE_VALUE)
+        return FAT_INIT_ENDIAN_ERROR;
+
+    // Verify packed structures
+    if (sizeof(struct fat_dir_entry) != FAT_DIR_ENTRY_SIZE)
+        return FAT_INIT_STRUCT_PACKING;
+
+    // Check the partition type code
+    switch(fs->currentsector.sector[PARTITION1_TYPECODE_LOCATION])
+    {
+        case 0x0B:
+        case 0x06:
+        case 0x0C:
+        case 0x0E:
+        case 0x0F:
+        case 0x05:
+            valid_partition = 1;
+        break;
+        case 0x00:
+            valid_partition = 0;
+            break;
+        default:
+            if (fs->currentsector.sector[PARTITION1_TYPECODE_LOCATION] <= 0x06)
+                valid_partition = 1;
+        break;
+    }
+
+    // Read LBA Begin for the file system
+    if (valid_partition)
+        fs->lba_begin = GET_32BIT_WORD(fs->currentsector.sector, PARTITION1_LBA_BEGIN_LOCATION);
+    // Else possibly MBR less disk
+    else
+        fs->lba_begin = 0;
+
+    // Load Volume 1 table into sector buffer
+    // (We may already have this in the buffer if MBR less drive!)
+    if (!fs->disk_io.read_media(fs->lba_begin, fs->currentsector.sector, 1))
+        return FAT_INIT_MEDIA_ACCESS_ERROR;
+
+    // Make sure there are 512 bytes per cluster
+    if (GET_16BIT_WORD(fs->currentsector.sector, 0x0B) != FAT_SECTOR_SIZE)
+        return FAT_INIT_INVALID_SECTOR_SIZE;
+
+    // Load Parameters of FAT partition
+    fs->sectors_per_cluster = fs->currentsector.sector[BPB_SECPERCLUS];
+    reserved_sectors = GET_16BIT_WORD(fs->currentsector.sector, BPB_RSVDSECCNT);
+    num_of_fats = fs->currentsector.sector[BPB_NUMFATS];
+    fs->root_entry_count = GET_16BIT_WORD(fs->currentsector.sector, BPB_ROOTENTCNT);
+
+    if(GET_16BIT_WORD(fs->currentsector.sector, BPB_FATSZ16) != 0)
+        fs->fat_sectors = GET_16BIT_WORD(fs->currentsector.sector, BPB_FATSZ16);
+    else
+        fs->fat_sectors = GET_32BIT_WORD(fs->currentsector.sector, BPB_FAT32_FATSZ32);
+
+    // For FAT32 (which this may be)
+    fs->rootdir_first_cluster = GET_32BIT_WORD(fs->currentsector.sector, BPB_FAT32_ROOTCLUS);
+    fs->fs_info_sector = GET_16BIT_WORD(fs->currentsector.sector, BPB_FAT32_FSINFO);
+
+    // For FAT16 (which this may be), rootdir_first_cluster is actuall rootdir_first_sector
+    fs->rootdir_first_sector = reserved_sectors + (num_of_fats * fs->fat_sectors);
+    fs->rootdir_sectors = ((fs->root_entry_count * 32) + (FAT_SECTOR_SIZE - 1)) / FAT_SECTOR_SIZE;
+
+    // First FAT LBA address
+    fs->fat_begin_lba = fs->lba_begin + reserved_sectors;
+
+    // The address of the first data cluster on this volume
+    fs->cluster_begin_lba = fs->fat_begin_lba + (num_of_fats * fs->fat_sectors);
+
+    if (GET_16BIT_WORD(fs->currentsector.sector, 0x1FE) != 0xAA55) // This signature should be AA55
+        return FAT_INIT_INVALID_SIGNATURE;
+
+    // Calculate the root dir sectors
+    root_dir_sectors = ((GET_16BIT_WORD(fs->currentsector.sector, BPB_ROOTENTCNT) * 32) + (GET_16BIT_WORD(fs->currentsector.sector, BPB_BYTSPERSEC) - 1)) / GET_16BIT_WORD(fs->currentsector.sector, BPB_BYTSPERSEC);
+
+    if(GET_16BIT_WORD(fs->currentsector.sector, BPB_FATSZ16) != 0)
+        FATSz = GET_16BIT_WORD(fs->currentsector.sector, BPB_FATSZ16);
+    else
+        FATSz = GET_32BIT_WORD(fs->currentsector.sector, BPB_FAT32_FATSZ32);
+
+    if(GET_16BIT_WORD(fs->currentsector.sector, BPB_TOTSEC16) != 0)
+        total_sectors = GET_16BIT_WORD(fs->currentsector.sector, BPB_TOTSEC16);
+    else
+        total_sectors = GET_32BIT_WORD(fs->currentsector.sector, BPB_TOTSEC32);
+
+    data_sectors = total_sectors - (GET_16BIT_WORD(fs->currentsector.sector, BPB_RSVDSECCNT) + (fs->currentsector.sector[BPB_NUMFATS] * FATSz) + root_dir_sectors);
+
+    // Find out which version of FAT this is...
+    if (fs->sectors_per_cluster != 0)
+    {
+        count_of_clusters = data_sectors / fs->sectors_per_cluster;
+
+        if(count_of_clusters < 4085)
+            // Volume is FAT12
+            return FAT_INIT_WRONG_FILESYS_TYPE;
+        else if(count_of_clusters < 65525)
+        {
+            // Clear this FAT32 specific param
+            fs->rootdir_first_cluster = 0;
+
+            // Volume is FAT16
+            fs->fat_type = FAT_TYPE_16;
+            return FAT_INIT_OK;
+        }
+        else
+        {
+            // Volume is FAT32
+            fs->fat_type = FAT_TYPE_32;
+            return FAT_INIT_OK;
+        }
+    }
+    else
+        return FAT_INIT_WRONG_FILESYS_TYPE;
+}
+//-----------------------------------------------------------------------------
+// fatfs_lba_of_cluster: This function converts a cluster number into a sector /
+// LBA number.
+//-----------------------------------------------------------------------------
+uint32 fatfs_lba_of_cluster(struct fatfs *fs, uint32 Cluster_Number)
+{
+    if (fs->fat_type == FAT_TYPE_16)
+        return (fs->cluster_begin_lba + (fs->root_entry_count * 32 / FAT_SECTOR_SIZE) + ((Cluster_Number-2) * fs->sectors_per_cluster));
+    else
+        return ((fs->cluster_begin_lba + ((Cluster_Number-2)*fs->sectors_per_cluster)));
+}
+//-----------------------------------------------------------------------------
+// fatfs_sector_read:
+//-----------------------------------------------------------------------------
+int fatfs_sector_read(struct fatfs *fs, uint32 lba, uint8 *target, uint32 count)
+{
+    return fs->disk_io.read_media(lba, target, count);
+}
+//-----------------------------------------------------------------------------
+// fatfs_sector_write:
+//-----------------------------------------------------------------------------
+int fatfs_sector_write(struct fatfs *fs, uint32 lba, uint8 *target, uint32 count)
+{
+    return fs->disk_io.write_media(lba, target, count);
+}
+//-----------------------------------------------------------------------------
+// fatfs_sector_reader: From the provided startcluster and sector offset
+// Returns True if success, returns False if not (including if read out of range)
+//-----------------------------------------------------------------------------
+int fatfs_sector_reader(struct fatfs *fs, uint32 start_cluster, uint32 offset, uint8 *target)
+{
+    uint32 sector_to_read = 0;
+    uint32 cluster_to_read = 0;
+    uint32 cluster_chain = 0;
+    uint32 i;
+    uint32 lba;
+
+    // FAT16 Root directory
+    if (fs->fat_type == FAT_TYPE_16 && start_cluster == 0)
+    {
+        if (offset < fs->rootdir_sectors)
+            lba = fs->lba_begin + fs->rootdir_first_sector + offset;
+        else
+            return 0;
+    }
+    // FAT16/32 Other
+    else
+    {
+        // Set start of cluster chain to initial value
+        cluster_chain = start_cluster;
+
+        // Find parameters
+        cluster_to_read = offset / fs->sectors_per_cluster;
+        sector_to_read = offset - (cluster_to_read*fs->sectors_per_cluster);
+
+        // Follow chain to find cluster to read
+        for (i=0; idisk_io.read_media(lba, target, 1);
+    // Else read sector if not already loaded
+    else if (lba != fs->currentsector.address)
+    {
+        fs->currentsector.address = lba;
+        return fs->disk_io.read_media(fs->currentsector.address, fs->currentsector.sector, 1);
+    }
+    else
+        return 1;
+}
+//-----------------------------------------------------------------------------
+// fatfs_read_sector: Read from the provided cluster and sector offset
+// Returns True if success, returns False if not
+//-----------------------------------------------------------------------------
+int fatfs_read_sector(struct fatfs *fs, uint32 cluster, uint32 sector, uint8 *target)
+{
+    // FAT16 Root directory
+    if (fs->fat_type == FAT_TYPE_16 && cluster == 0)
+    {
+        uint32 lba;
+
+        // In FAT16, there are a limited amount of sectors in root dir!
+        if (sector < fs->rootdir_sectors)
+            lba = fs->lba_begin + fs->rootdir_first_sector + sector;
+        else
+            return 0;
+
+        // User target buffer passed in
+        if (target)
+        {
+            // Read from disk
+            return fs->disk_io.read_media(lba, target, 1);
+        }
+        else
+        {
+            // Calculate read address
+            fs->currentsector.address = lba;
+
+            // Read from disk
+            return fs->disk_io.read_media(fs->currentsector.address, fs->currentsector.sector, 1);
+        }
+    }
+    // FAT16/32 Other
+    else
+    {
+        // User target buffer passed in
+        if (target)
+        {
+            // Calculate read address
+            uint32 lba = fatfs_lba_of_cluster(fs, cluster) + sector;
+
+            // Read from disk
+            return fs->disk_io.read_media(lba, target, 1);
+        }
+        else
+        {
+            // Calculate write address
+            fs->currentsector.address = fatfs_lba_of_cluster(fs, cluster)+sector;
+
+            // Read from disk
+            return fs->disk_io.read_media(fs->currentsector.address, fs->currentsector.sector, 1);
+        }
+    }
+}
+//-----------------------------------------------------------------------------
+// fatfs_write_sector: Write to the provided cluster and sector offset
+// Returns True if success, returns False if not
+//-----------------------------------------------------------------------------
+#if FATFS_INC_WRITE_SUPPORT
+int fatfs_write_sector(struct fatfs *fs, uint32 cluster, uint32 sector, uint8 *target)
+{
+    // No write access?
+    if (!fs->disk_io.write_media)
+        return 0;
+
+    // FAT16 Root directory
+    if (fs->fat_type == FAT_TYPE_16 && cluster == 0)
+    {
+        uint32 lba;
+
+        // In FAT16 we cannot extend the root dir!
+        if (sector < fs->rootdir_sectors)
+            lba = fs->lba_begin + fs->rootdir_first_sector + sector;
+        else
+            return 0;
+
+        // User target buffer passed in
+        if (target)
+        {
+            // Write to disk
+            return fs->disk_io.write_media(lba, target, 1);
+        }
+        else
+        {
+            // Calculate write address
+            fs->currentsector.address = lba;
+
+            // Write to disk
+            return fs->disk_io.write_media(fs->currentsector.address, fs->currentsector.sector, 1);
+        }
+    }
+    // FAT16/32 Other
+    else
+    {
+        // User target buffer passed in
+        if (target)
+        {
+            // Calculate write address
+            uint32 lba = fatfs_lba_of_cluster(fs, cluster) + sector;
+
+            // Write to disk
+            return fs->disk_io.write_media(lba, target, 1);
+        }
+        else
+        {
+            // Calculate write address
+            fs->currentsector.address = fatfs_lba_of_cluster(fs, cluster)+sector;
+
+            // Write to disk
+            return fs->disk_io.write_media(fs->currentsector.address, fs->currentsector.sector, 1);
+        }
+    }
+}
+#endif
+//-----------------------------------------------------------------------------
+// fatfs_show_details: Show the details about the filesystem
+//-----------------------------------------------------------------------------
+void fatfs_show_details(struct fatfs *fs)
+{
+    FAT_PRINTF(("FAT details:\r\n"));
+    FAT_PRINTF((" Type =%s", (fs->fat_type == FAT_TYPE_32) ? "FAT32": "FAT16"));
+    FAT_PRINTF((" Root Dir First Cluster = %x\r\n", fs->rootdir_first_cluster));
+    FAT_PRINTF((" FAT Begin LBA = 0x%x\r\n",fs->fat_begin_lba));
+    FAT_PRINTF((" Cluster Begin LBA = 0x%x\r\n",fs->cluster_begin_lba));
+    FAT_PRINTF((" Sectors Per Cluster = %d\r\n", fs->sectors_per_cluster));
+}
+//-----------------------------------------------------------------------------
+// fatfs_get_root_cluster: Get the root dir cluster
+//-----------------------------------------------------------------------------
+uint32 fatfs_get_root_cluster(struct fatfs *fs)
+{
+    // NOTE: On FAT16 this will be 0 which has a special meaning...
+    return fs->rootdir_first_cluster;
+}
+//-------------------------------------------------------------
+// fatfs_get_file_entry: Find the file entry for a filename
+//-------------------------------------------------------------
+uint32 fatfs_get_file_entry(struct fatfs *fs, uint32 Cluster, char *name_to_find, struct fat_dir_entry *sfEntry)
+{
+    uint8 item=0;
+    uint16 recordoffset = 0;
+    uint8 i=0;
+    int x=0;
+    char *long_filename = NULL;
+    char short_filename[13];
+    struct lfn_cache lfn;
+    int dotRequired = 0;
+    struct fat_dir_entry *directoryEntry;
+
+    fatfs_lfn_cache_init(&lfn, 1);
+
+    // Main cluster following loop
+    while (1)
+    {
+        // Read sector
+        if (fatfs_sector_reader(fs, Cluster, x++, 0)) // If sector read was successfull
+        {
+            // Analyse Sector
+            for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++)
+            {
+                // Create the multiplier for sector access
+                recordoffset = FAT_DIR_ENTRY_SIZE * item;
+
+                // Overlay directory entry over buffer
+                directoryEntry = (struct fat_dir_entry*)(fs->currentsector.sector+recordoffset);
+
+#if FATFS_INC_LFN_SUPPORT
+                // Long File Name Text Found
+                if (fatfs_entry_lfn_text(directoryEntry) )
+                    fatfs_lfn_cache_entry(&lfn, fs->currentsector.sector+recordoffset);
+
+                // If Invalid record found delete any long file name information collated
+                else if (fatfs_entry_lfn_invalid(directoryEntry) )
+                    fatfs_lfn_cache_init(&lfn, 0);
+
+                // Normal SFN Entry and Long text exists
+                else if (fatfs_entry_lfn_exists(&lfn, directoryEntry) )
+                {
+                    long_filename = fatfs_lfn_cache_get(&lfn);
+
+                    // Compare names to see if they match
+                    if (fatfs_compare_names(long_filename, name_to_find))
+                    {
+                        memcpy(sfEntry,directoryEntry,sizeof(struct fat_dir_entry));
+                        return 1;
+                    }
+
+                    fatfs_lfn_cache_init(&lfn, 0);
+                }
+                else
+#endif
+                // Normal Entry, only 8.3 Text
+                if (fatfs_entry_sfn_only(directoryEntry) )
+                {
+                    memset(short_filename, 0, sizeof(short_filename));
+
+                    // Copy name to string
+                    for (i=0; i<8; i++)
+                        short_filename[i] = directoryEntry->Name[i];
+
+                    // Extension
+                    dotRequired = 0;
+                    for (i=8; i<11; i++)
+                    {
+                        short_filename[i+1] = directoryEntry->Name[i];
+                        if (directoryEntry->Name[i] != ' ')
+                            dotRequired = 1;
+                    }
+
+                    // Dot only required if extension present
+                    if (dotRequired)
+                    {
+                        // If not . or .. entry
+                        if (short_filename[0]!='.')
+                            short_filename[8] = '.';
+                        else
+                            short_filename[8] = ' ';
+                    }
+                    else
+                        short_filename[8] = ' ';
+
+                    // Compare names to see if they match
+                    if (fatfs_compare_names(short_filename, name_to_find))
+                    {
+                        memcpy(sfEntry,directoryEntry,sizeof(struct fat_dir_entry));
+                        return 1;
+                    }
+
+                    fatfs_lfn_cache_init(&lfn, 0);
+                }
+            } // End of if
+        }
+        else
+            break;
+    } // End of while loop
+
+    return 0;
+}
+//-------------------------------------------------------------
+// fatfs_sfn_exists: Check if a short filename exists.
+// NOTE: shortname is XXXXXXXXYYY not XXXXXXXX.YYY
+//-------------------------------------------------------------
+#if FATFS_INC_WRITE_SUPPORT
+int fatfs_sfn_exists(struct fatfs *fs, uint32 Cluster, char *shortname)
+{
+    uint8 item=0;
+    uint16 recordoffset = 0;
+    int x=0;
+    struct fat_dir_entry *directoryEntry;
+
+    // Main cluster following loop
+    while (1)
+    {
+        // Read sector
+        if (fatfs_sector_reader(fs, Cluster, x++, 0)) // If sector read was successfull
+        {
+            // Analyse Sector
+            for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++)
+            {
+                // Create the multiplier for sector access
+                recordoffset = FAT_DIR_ENTRY_SIZE * item;
+
+                // Overlay directory entry over buffer
+                directoryEntry = (struct fat_dir_entry*)(fs->currentsector.sector+recordoffset);
+
+#if FATFS_INC_LFN_SUPPORT
+                // Long File Name Text Found
+                if (fatfs_entry_lfn_text(directoryEntry) )
+                    ;
+
+                // If Invalid record found delete any long file name information collated
+                else if (fatfs_entry_lfn_invalid(directoryEntry) )
+                    ;
+                else
+#endif
+                // Normal Entry, only 8.3 Text
+                if (fatfs_entry_sfn_only(directoryEntry) )
+                {
+                    if (strncmp((const char*)directoryEntry->Name, shortname, 11)==0)
+                        return 1;
+                }
+            } // End of if
+        }
+        else
+            break;
+    } // End of while loop
+
+    return 0;
+}
+#endif
+//-------------------------------------------------------------
+// fatfs_update_timestamps: Update date/time details
+//-------------------------------------------------------------
+#if FATFS_INC_TIME_DATE_SUPPORT
+int fatfs_update_timestamps(struct fat_dir_entry *directoryEntry, int create, int modify, int access)
+{
+    time_t time_now;
+    struct tm * time_info;
+    uint16 fat_time;
+    uint16 fat_date;
+
+    // Get system time
+    time(&time_now);
+
+    // Convert to local time
+    time_info = localtime(&time_now);
+
+    // Convert time to FAT format
+    fat_time = fatfs_convert_to_fat_time(time_info->tm_hour, time_info->tm_min, time_info->tm_sec);
+
+    // Convert date to FAT format
+    fat_date = fatfs_convert_to_fat_date(time_info->tm_mday, time_info->tm_mon + 1, time_info->tm_year + 1900);
+
+    // Update requested fields
+    if (create)
+    {
+        directoryEntry->CrtTime[1] = fat_time >> 8;
+        directoryEntry->CrtTime[0] = fat_time >> 0;
+        directoryEntry->CrtDate[1] = fat_date >> 8;
+        directoryEntry->CrtDate[0] = fat_date >> 0;
+    }
+
+    if (modify)
+    {
+        directoryEntry->WrtTime[1] = fat_time >> 8;
+        directoryEntry->WrtTime[0] = fat_time >> 0;
+        directoryEntry->WrtDate[1] = fat_date >> 8;
+        directoryEntry->WrtDate[0] = fat_date >> 0;
+    }
+
+    if (access)
+    {
+        directoryEntry->LstAccDate[1] = fat_time >> 8;
+        directoryEntry->LstAccDate[0] = fat_time >> 0;
+        directoryEntry->LstAccDate[1] = fat_date >> 8;
+        directoryEntry->LstAccDate[0] = fat_date >> 0;
+    }
+
+    return 1;
+}
+#endif
+//-------------------------------------------------------------
+// fatfs_update_file_length: Find a SFN entry and update it
+// NOTE: shortname is XXXXXXXXYYY not XXXXXXXX.YYY
+//-------------------------------------------------------------
+#if FATFS_INC_WRITE_SUPPORT
+int fatfs_update_file_length(struct fatfs *fs, uint32 Cluster, char *shortname, uint32 fileLength)
+{
+    uint8 item=0;
+    uint16 recordoffset = 0;
+    int x=0;
+    struct fat_dir_entry *directoryEntry;
+
+    // No write access?
+    if (!fs->disk_io.write_media)
+        return 0;
+
+    // Main cluster following loop
+    while (1)
+    {
+        // Read sector
+        if (fatfs_sector_reader(fs, Cluster, x++, 0)) // If sector read was successfull
+        {
+            // Analyse Sector
+            for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++)
+            {
+                // Create the multiplier for sector access
+                recordoffset = FAT_DIR_ENTRY_SIZE * item;
+
+                // Overlay directory entry over buffer
+                directoryEntry = (struct fat_dir_entry*)(fs->currentsector.sector+recordoffset);
+
+#if FATFS_INC_LFN_SUPPORT
+                // Long File Name Text Found
+                if (fatfs_entry_lfn_text(directoryEntry) )
+                    ;
+
+                // If Invalid record found delete any long file name information collated
+                else if (fatfs_entry_lfn_invalid(directoryEntry) )
+                    ;
+
+                // Normal Entry, only 8.3 Text
+                else
+#endif
+                if (fatfs_entry_sfn_only(directoryEntry) )
+                {
+                    if (strncmp((const char*)directoryEntry->Name, shortname, 11)==0)
+                    {
+                        directoryEntry->FileSize = FAT_HTONL(fileLength);
+
+#if FATFS_INC_TIME_DATE_SUPPORT
+                        // Update access / modify time & date
+                        fatfs_update_timestamps(directoryEntry, 0, 1, 1);
+#endif
+
+                        // Update sfn entry
+                        memcpy((uint8*)(fs->currentsector.sector+recordoffset), (uint8*)directoryEntry, sizeof(struct fat_dir_entry));
+
+                        // Write sector back
+                        return fs->disk_io.write_media(fs->currentsector.address, fs->currentsector.sector, 1);
+                    }
+                }
+            } // End of if
+        }
+        else
+            break;
+    } // End of while loop
+
+    return 0;
+}
+#endif
+//-------------------------------------------------------------
+// fatfs_mark_file_deleted: Find a SFN entry and mark if as deleted
+// NOTE: shortname is XXXXXXXXYYY not XXXXXXXX.YYY
+//-------------------------------------------------------------
+#if FATFS_INC_WRITE_SUPPORT
+int fatfs_mark_file_deleted(struct fatfs *fs, uint32 Cluster, char *shortname)
+{
+    uint8 item=0;
+    uint16 recordoffset = 0;
+    int x=0;
+    struct fat_dir_entry *directoryEntry;
+
+    // No write access?
+    if (!fs->disk_io.write_media)
+        return 0;
+
+    // Main cluster following loop
+    while (1)
+    {
+        // Read sector
+        if (fatfs_sector_reader(fs, Cluster, x++, 0)) // If sector read was successfull
+        {
+            // Analyse Sector
+            for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++)
+            {
+                // Create the multiplier for sector access
+                recordoffset = FAT_DIR_ENTRY_SIZE * item;
+
+                // Overlay directory entry over buffer
+                directoryEntry = (struct fat_dir_entry*)(fs->currentsector.sector+recordoffset);
+
+#if FATFS_INC_LFN_SUPPORT
+                // Long File Name Text Found
+                if (fatfs_entry_lfn_text(directoryEntry) )
+                    ;
+
+                // If Invalid record found delete any long file name information collated
+                else if (fatfs_entry_lfn_invalid(directoryEntry) )
+                    ;
+
+                // Normal Entry, only 8.3 Text
+                else
+#endif
+                if (fatfs_entry_sfn_only(directoryEntry) )
+                {
+                    if (strncmp((const char *)directoryEntry->Name, shortname, 11)==0)
+                    {
+                        // Mark as deleted
+                        directoryEntry->Name[0] = FILE_HEADER_DELETED;
+
+#if FATFS_INC_TIME_DATE_SUPPORT
+                        // Update access / modify time & date
+                        fatfs_update_timestamps(directoryEntry, 0, 1, 1);
+#endif
+
+                        // Update sfn entry
+                        memcpy((uint8*)(fs->currentsector.sector+recordoffset), (uint8*)directoryEntry, sizeof(struct fat_dir_entry));
+
+                        // Write sector back
+                        return fs->disk_io.write_media(fs->currentsector.address, fs->currentsector.sector, 1);
+                    }
+                }
+            } // End of if
+        }
+        else
+            break;
+    } // End of while loop
+
+    return 0;
+}
+#endif
+//-----------------------------------------------------------------------------
+// fatfs_list_directory_start: Initialise a directory listing procedure
+//-----------------------------------------------------------------------------
+#if FATFS_DIR_LIST_SUPPORT
+void fatfs_list_directory_start(struct fatfs *fs, struct fs_dir_list_status *dirls, uint32 StartCluster)
+{
+    dirls->cluster = StartCluster;
+    dirls->sector = 0;
+    dirls->offset = 0;
+}
+#endif
+//-----------------------------------------------------------------------------
+// fatfs_list_directory_next: Get the next entry in the directory.
+// Returns: 1 = found, 0 = end of listing
+//-----------------------------------------------------------------------------
+#if FATFS_DIR_LIST_SUPPORT
+int fatfs_list_directory_next(struct fatfs *fs, struct fs_dir_list_status *dirls, struct fs_dir_ent *entry)
+{
+    uint8 i,item;
+    uint16 recordoffset;
+    struct fat_dir_entry *directoryEntry;
+    char *long_filename = NULL;
+    char short_filename[13];
+    struct lfn_cache lfn;
+    int dotRequired = 0;
+    int result = 0;
+
+    // Initialise LFN cache first
+    fatfs_lfn_cache_init(&lfn, 0);
+
+    while (1)
+    {
+        // If data read OK
+        if (fatfs_sector_reader(fs, dirls->cluster, dirls->sector, 0))
+        {
+            // Maximum of 16 directory entries
+            for (item = dirls->offset; item < FAT_DIR_ENTRIES_PER_SECTOR; item++)
+            {
+                // Increase directory offset
+                recordoffset = FAT_DIR_ENTRY_SIZE * item;
+
+                // Overlay directory entry over buffer
+                directoryEntry = (struct fat_dir_entry*)(fs->currentsector.sector+recordoffset);
+
+#if FATFS_INC_LFN_SUPPORT
+                // Long File Name Text Found
+                if ( fatfs_entry_lfn_text(directoryEntry) )
+                    fatfs_lfn_cache_entry(&lfn, fs->currentsector.sector+recordoffset);
+
+                // If Invalid record found delete any long file name information collated
+                else if ( fatfs_entry_lfn_invalid(directoryEntry) )
+                    fatfs_lfn_cache_init(&lfn, 0);
+
+                // Normal SFN Entry and Long text exists
+                else if (fatfs_entry_lfn_exists(&lfn, directoryEntry) )
+                {
+                    // Get text
+                    long_filename = fatfs_lfn_cache_get(&lfn);
+                    strncpy(entry->filename, long_filename, FATFS_MAX_LONG_FILENAME-1);
+
+                    if (fatfs_entry_is_dir(directoryEntry))
+                        entry->is_dir = 1;
+                    else
+                        entry->is_dir = 0;
+
+#if FATFS_INC_TIME_DATE_SUPPORT
+                    // Get time / dates
+                    entry->create_time = ((uint16)directoryEntry->CrtTime[1] << 8) | directoryEntry->CrtTime[0];
+                    entry->create_date = ((uint16)directoryEntry->CrtDate[1] << 8) | directoryEntry->CrtDate[0];
+                    entry->access_date = ((uint16)directoryEntry->LstAccDate[1] << 8) | directoryEntry->LstAccDate[0];
+                    entry->write_time  = ((uint16)directoryEntry->WrtTime[1] << 8) | directoryEntry->WrtTime[0];
+                    entry->write_date  = ((uint16)directoryEntry->WrtDate[1] << 8) | directoryEntry->WrtDate[0];
+#endif
+
+                    entry->size = FAT_HTONL(directoryEntry->FileSize);
+                    entry->cluster = (FAT_HTONS(directoryEntry->FstClusHI)<<16) | FAT_HTONS(directoryEntry->FstClusLO);
+
+                    // Next starting position
+                    dirls->offset = item + 1;
+                    result = 1;
+                    return 1;
+                }
+                // Normal Entry, only 8.3 Text
+                else
+#endif
+                if ( fatfs_entry_sfn_only(directoryEntry) )
+                {
+                    fatfs_lfn_cache_init(&lfn, 0);
+
+                    memset(short_filename, 0, sizeof(short_filename));
+
+                    // Copy name to string
+                    for (i=0; i<8; i++)
+                        short_filename[i] = directoryEntry->Name[i];
+
+                    // Extension
+                    dotRequired = 0;
+                    for (i=8; i<11; i++)
+                    {
+                        short_filename[i+1] = directoryEntry->Name[i];
+                        if (directoryEntry->Name[i] != ' ')
+                            dotRequired = 1;
+                    }
+
+                    // Dot only required if extension present
+                    if (dotRequired)
+                    {
+                        // If not . or .. entry
+                        if (short_filename[0]!='.')
+                            short_filename[8] = '.';
+                        else
+                            short_filename[8] = ' ';
+                    }
+                    else
+                        short_filename[8] = ' ';
+
+                    fatfs_get_sfn_display_name(entry->filename, short_filename);
+
+                    if (fatfs_entry_is_dir(directoryEntry))
+                        entry->is_dir = 1;
+                    else
+                        entry->is_dir = 0;
+
+#if FATFS_INC_TIME_DATE_SUPPORT
+                    // Get time / dates
+                    entry->create_time = ((uint16)directoryEntry->CrtTime[1] << 8) | directoryEntry->CrtTime[0];
+                    entry->create_date = ((uint16)directoryEntry->CrtDate[1] << 8) | directoryEntry->CrtDate[0];
+                    entry->access_date = ((uint16)directoryEntry->LstAccDate[1] << 8) | directoryEntry->LstAccDate[0];
+                    entry->write_time  = ((uint16)directoryEntry->WrtTime[1] << 8) | directoryEntry->WrtTime[0];
+                    entry->write_date  = ((uint16)directoryEntry->WrtDate[1] << 8) | directoryEntry->WrtDate[0];
+#endif
+
+                    entry->size = FAT_HTONL(directoryEntry->FileSize);
+                    entry->cluster = (FAT_HTONS(directoryEntry->FstClusHI)<<16) | FAT_HTONS(directoryEntry->FstClusLO);
+
+                    // Next starting position
+                    dirls->offset = item + 1;
+                    result = 1;
+                    return 1;
+                }
+            }// end of for
+
+            // If reached end of the dir move onto next sector
+            dirls->sector++;
+            dirls->offset = 0;
+        }
+        else
+            break;
+    }
+
+    return result;
+}
+#endif
diff --git a/sys/fs/fat/fat_access.h b/sys/fs/fat/fat_access.h
new file mode 100644
index 0000000..1752387
--- /dev/null
+++ b/sys/fs/fat/fat_access.h
@@ -0,0 +1,133 @@
+#ifndef __FAT_ACCESS_H__
+#define __FAT_ACCESS_H__
+
+#include "fat_defs.h"
+#include "fat_opts.h"
+
+//-----------------------------------------------------------------------------
+// Defines
+//-----------------------------------------------------------------------------
+#define FAT_INIT_OK                         0
+#define FAT_INIT_MEDIA_ACCESS_ERROR         (-1)
+#define FAT_INIT_INVALID_SECTOR_SIZE        (-2)
+#define FAT_INIT_INVALID_SIGNATURE          (-3)
+#define FAT_INIT_ENDIAN_ERROR               (-4)
+#define FAT_INIT_WRONG_FILESYS_TYPE         (-5)
+#define FAT_INIT_WRONG_PARTITION_TYPE       (-6)
+#define FAT_INIT_STRUCT_PACKING             (-7)
+
+#define FAT_DIR_ENTRIES_PER_SECTOR          (FAT_SECTOR_SIZE / FAT_DIR_ENTRY_SIZE)
+
+//-----------------------------------------------------------------------------
+// Function Pointers
+//-----------------------------------------------------------------------------
+typedef int (*fn_diskio_read) (uint32 sector, uint8 *buffer, uint32 sector_count);
+typedef int (*fn_diskio_write)(uint32 sector, uint8 *buffer, uint32 sector_count);
+
+//-----------------------------------------------------------------------------
+// Structures
+//-----------------------------------------------------------------------------
+struct disk_if
+{
+    // User supplied function pointers for disk IO
+    fn_diskio_read          read_media;
+    fn_diskio_write         write_media;
+};
+
+// Forward declaration
+struct fat_buffer;
+
+struct fat_buffer
+{
+    uint8                   sector[FAT_SECTOR_SIZE * FAT_BUFFER_SECTORS];
+    uint32                  address;
+    int                     dirty;
+    uint8 *                 ptr;
+
+    // Next in chain of sector buffers
+    struct fat_buffer       *next;
+};
+
+typedef enum eFatType
+{
+    FAT_TYPE_16,
+    FAT_TYPE_32
+} tFatType;
+
+struct fatfs
+{
+    // Filesystem globals
+    uint8                   sectors_per_cluster;
+    uint32                  cluster_begin_lba;
+    uint32                  rootdir_first_cluster;
+    uint32                  rootdir_first_sector;
+    uint32                  rootdir_sectors;
+    uint32                  fat_begin_lba;
+    uint16                  fs_info_sector;
+    uint32                  lba_begin;
+    uint32                  fat_sectors;
+    uint32                  next_free_cluster;
+    uint16                  root_entry_count;
+    uint16                  reserved_sectors;
+    uint8                   num_of_fats;
+    tFatType                fat_type;
+
+    // Disk/Media API
+    struct disk_if          disk_io;
+
+    // [Optional] Thread Safety
+    void                    (*fl_lock)(void);
+    void                    (*fl_unlock)(void);
+
+    // Working buffer
+    struct fat_buffer        currentsector;
+
+    // FAT Buffer
+    struct fat_buffer        *fat_buffer_head;
+    struct fat_buffer        fat_buffers[FAT_BUFFERS];
+};
+
+struct fs_dir_list_status
+{
+    uint32                  sector;
+    uint32                  cluster;
+    uint8                   offset;
+};
+
+struct fs_dir_ent
+{
+    char                    filename[FATFS_MAX_LONG_FILENAME];
+    uint8                   is_dir;
+    uint32                  cluster;
+    uint32                  size;
+
+#if FATFS_INC_TIME_DATE_SUPPORT
+    uint16                  access_date;
+    uint16                  write_time;
+    uint16                  write_date;
+    uint16                  create_date;
+    uint16                  create_time;
+#endif
+};
+
+//-----------------------------------------------------------------------------
+// Prototypes
+//-----------------------------------------------------------------------------
+int     fatfs_init(struct fatfs *fs);
+uint32  fatfs_lba_of_cluster(struct fatfs *fs, uint32 Cluster_Number);
+int     fatfs_sector_reader(struct fatfs *fs, uint32 Startcluster, uint32 offset, uint8 *target);
+int     fatfs_sector_read(struct fatfs *fs, uint32 lba, uint8 *target, uint32 count);
+int     fatfs_sector_write(struct fatfs *fs, uint32 lba, uint8 *target, uint32 count);
+int     fatfs_read_sector(struct fatfs *fs, uint32 cluster, uint32 sector, uint8 *target);
+int     fatfs_write_sector(struct fatfs *fs, uint32 cluster, uint32 sector, uint8 *target);
+void    fatfs_show_details(struct fatfs *fs);
+uint32  fatfs_get_root_cluster(struct fatfs *fs);
+uint32  fatfs_get_file_entry(struct fatfs *fs, uint32 Cluster, char *nametofind, struct fat_dir_entry *sfEntry);
+int     fatfs_sfn_exists(struct fatfs *fs, uint32 Cluster, char *shortname);
+int     fatfs_update_file_length(struct fatfs *fs, uint32 Cluster, char *shortname, uint32 fileLength);
+int     fatfs_mark_file_deleted(struct fatfs *fs, uint32 Cluster, char *shortname);
+void    fatfs_list_directory_start(struct fatfs *fs, struct fs_dir_list_status *dirls, uint32 StartCluster);
+int     fatfs_list_directory_next(struct fatfs *fs, struct fs_dir_list_status *dirls, struct fs_dir_ent *entry);
+int     fatfs_update_timestamps(struct fat_dir_entry *directoryEntry, int create, int modify, int access);
+
+#endif
diff --git a/sys/fs/fat/fat_cache.c b/sys/fs/fat/fat_cache.c
new file mode 100644
index 0000000..de77e6a
--- /dev/null
+++ b/sys/fs/fat/fat_cache.c
@@ -0,0 +1,91 @@
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//                            FAT16/32 File IO Library
+//                                    V2.6
+//                              Ultra-Embedded.com
+//                            Copyright 2003 - 2012
+//
+//                         Email: admin@ultra-embedded.com
+//
+//                                License: GPL
+//   If you would like a version with a more permissive license for use in
+//   closed source commercial applications please contact me for details.
+//-----------------------------------------------------------------------------
+//
+// This file is part of FAT File IO Library.
+//
+// FAT File IO Library is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// FAT File IO Library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FAT File IO Library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+#include 
+#include "fat_cache.h"
+
+// Per file cluster chain caching used to improve performance.
+// This does not have to be enabled for architectures with low
+// memory space.
+
+//-----------------------------------------------------------------------------
+// fatfs_cache_init:
+//-----------------------------------------------------------------------------
+int fatfs_cache_init(struct fatfs *fs, FL_FILE *file)
+{
+#ifdef FAT_CLUSTER_CACHE_ENTRIES
+    int i;
+
+    for (i=0;icluster_cache_idx[i] = 0xFFFFFFFF; // Not used
+        file->cluster_cache_data[i] = 0;
+    }
+#endif
+
+    return 1;
+}
+//-----------------------------------------------------------------------------
+// fatfs_cache_get_next_cluster:
+//-----------------------------------------------------------------------------
+int fatfs_cache_get_next_cluster(struct fatfs *fs, FL_FILE *file, uint32 clusterIdx, uint32 *pNextCluster)
+{
+#ifdef FAT_CLUSTER_CACHE_ENTRIES
+    uint32 slot = clusterIdx % FAT_CLUSTER_CACHE_ENTRIES;
+
+    if (file->cluster_cache_idx[slot] == clusterIdx)
+    {
+        *pNextCluster = file->cluster_cache_data[slot];
+        return 1;
+    }
+#endif
+
+    return 0;
+}
+//-----------------------------------------------------------------------------
+// fatfs_cache_set_next_cluster:
+//-----------------------------------------------------------------------------
+int fatfs_cache_set_next_cluster(struct fatfs *fs, FL_FILE *file, uint32 clusterIdx, uint32 nextCluster)
+{
+#ifdef FAT_CLUSTER_CACHE_ENTRIES
+    uint32 slot = clusterIdx % FAT_CLUSTER_CACHE_ENTRIES;
+
+    if (file->cluster_cache_idx[slot] == clusterIdx)
+        file->cluster_cache_data[slot] = nextCluster;
+    else
+    {
+        file->cluster_cache_idx[slot] = clusterIdx;
+        file->cluster_cache_data[slot] = nextCluster;
+    }
+#endif
+
+    return 1;
+}
diff --git a/sys/fs/fat/fat_cache.h b/sys/fs/fat/fat_cache.h
new file mode 100644
index 0000000..348d5d3
--- /dev/null
+++ b/sys/fs/fat/fat_cache.h
@@ -0,0 +1,13 @@
+#ifndef __FAT_CACHE_H__
+#define __FAT_CACHE_H__
+
+#include "fat_filelib.h"
+
+//-----------------------------------------------------------------------------
+// Prototypes
+//-----------------------------------------------------------------------------
+int fatfs_cache_init(struct fatfs *fs, FL_FILE *file);
+int fatfs_cache_get_next_cluster(struct fatfs *fs, FL_FILE *file, uint32 clusterIdx, uint32 *pNextCluster);
+int fatfs_cache_set_next_cluster(struct fatfs *fs, FL_FILE *file, uint32 clusterIdx, uint32 nextCluster);
+
+#endif
diff --git a/sys/fs/fat/fat_defs.h b/sys/fs/fat/fat_defs.h
new file mode 100644
index 0000000..5fe8d6a
--- /dev/null
+++ b/sys/fs/fat/fat_defs.h
@@ -0,0 +1,128 @@
+#ifndef __FAT_DEFS_H__
+#define __FAT_DEFS_H__
+
+#include "fat_opts.h"
+#include "fat_types.h"
+
+//-----------------------------------------------------------------------------
+//            FAT32 Offsets
+//        Name                Offset
+//-----------------------------------------------------------------------------
+
+// Boot Sector
+#define BS_JMPBOOT              0    // Length = 3
+#define BS_OEMNAME              3    // Length = 8
+#define BPB_BYTSPERSEC          11    // Length = 2
+#define BPB_SECPERCLUS          13    // Length = 1
+#define BPB_RSVDSECCNT          14    // Length = 2
+#define BPB_NUMFATS             16    // Length = 1
+#define BPB_ROOTENTCNT          17    // Length = 2
+#define BPB_TOTSEC16            19    // Length = 2
+#define BPB_MEDIA               21    // Length = 1
+#define    BPB_FATSZ16          22    // Length = 2
+#define BPB_SECPERTRK           24    // Length = 2
+#define BPB_NUMHEADS            26    // Length = 2
+#define BPB_HIDDSEC             28    // Length = 4
+#define BPB_TOTSEC32            32    // Length = 4
+
+// FAT 12/16
+#define BS_FAT_DRVNUM           36    // Length = 1
+#define BS_FAT_BOOTSIG          38    // Length = 1
+#define BS_FAT_VOLID            39    // Length = 4
+#define BS_FAT_VOLLAB           43    // Length = 11
+#define BS_FAT_FILSYSTYPE       54    // Length = 8
+
+// FAT 32
+#define BPB_FAT32_FATSZ32       36    // Length = 4
+#define BPB_FAT32_EXTFLAGS      40    // Length = 2
+#define BPB_FAT32_FSVER         42    // Length = 2
+#define BPB_FAT32_ROOTCLUS      44    // Length = 4
+#define BPB_FAT32_FSINFO        48    // Length = 2
+#define BPB_FAT32_BKBOOTSEC     50    // Length = 2
+#define BS_FAT32_DRVNUM         64    // Length = 1
+#define BS_FAT32_BOOTSIG        66    // Length = 1
+#define BS_FAT32_VOLID          67    // Length = 4
+#define BS_FAT32_VOLLAB         71    // Length = 11
+#define BS_FAT32_FILSYSTYPE     82    // Length = 8
+
+//-----------------------------------------------------------------------------
+// FAT Types
+//-----------------------------------------------------------------------------
+#define FAT_TYPE_FAT12          1
+#define FAT_TYPE_FAT16          2
+#define FAT_TYPE_FAT32          3
+
+//-----------------------------------------------------------------------------
+// FAT32 Specific Statics
+//-----------------------------------------------------------------------------
+#define SIGNATURE_POSITION              510
+#define SIGNATURE_VALUE                 0xAA55
+#define PARTITION1_TYPECODE_LOCATION    450
+#define FAT32_TYPECODE1                 0x0B
+#define FAT32_TYPECODE2                 0x0C
+#define PARTITION1_LBA_BEGIN_LOCATION   454
+#define PARTITION1_SIZE_LOCATION        458
+
+#define FAT_DIR_ENTRY_SIZE              32
+#define FAT_SFN_SIZE_FULL               11
+#define FAT_SFN_SIZE_PARTIAL            8
+
+//-----------------------------------------------------------------------------
+// FAT32 File Attributes and Types
+//-----------------------------------------------------------------------------
+#define FILE_ATTR_READ_ONLY             0x01
+#define FILE_ATTR_HIDDEN                0x02
+#define FILE_ATTR_SYSTEM                0x04
+#define FILE_ATTR_SYSHID                0x06
+#define FILE_ATTR_VOLUME_ID             0x08
+#define FILE_ATTR_DIRECTORY             0x10
+#define FILE_ATTR_ARCHIVE               0x20
+#define FILE_ATTR_LFN_TEXT              0x0F
+#define FILE_HEADER_BLANK               0x00
+#define FILE_HEADER_DELETED             0xE5
+#define FILE_TYPE_DIR                   0x10
+#define FILE_TYPE_FILE                  0x20
+
+//-----------------------------------------------------------------------------
+// Time / Date details
+//-----------------------------------------------------------------------------
+#define FAT_TIME_HOURS_SHIFT            11
+#define FAT_TIME_HOURS_MASK             0x1F
+#define FAT_TIME_MINUTES_SHIFT          5
+#define FAT_TIME_MINUTES_MASK           0x3F
+#define FAT_TIME_SECONDS_SHIFT          0
+#define FAT_TIME_SECONDS_MASK           0x1F
+#define FAT_TIME_SECONDS_SCALE          2
+#define FAT_DATE_YEAR_SHIFT             9
+#define FAT_DATE_YEAR_MASK              0x7F
+#define FAT_DATE_MONTH_SHIFT            5
+#define FAT_DATE_MONTH_MASK             0xF
+#define FAT_DATE_DAY_SHIFT              0
+#define FAT_DATE_DAY_MASK               0x1F
+#define FAT_DATE_YEAR_OFFSET            1980
+
+//-----------------------------------------------------------------------------
+// Other Defines
+//-----------------------------------------------------------------------------
+#define FAT32_LAST_CLUSTER              0xFFFFFFFF
+#define FAT32_INVALID_CLUSTER           0xFFFFFFFF
+
+STRUCT_PACK_BEGIN
+struct fat_dir_entry STRUCT_PACK
+{
+    uint8 Name[11];
+    uint8 Attr;
+    uint8 NTRes;
+    uint8 CrtTimeTenth;
+    uint8 CrtTime[2];
+    uint8 CrtDate[2];
+    uint8 LstAccDate[2];
+    uint16 FstClusHI;
+    uint8 WrtTime[2];
+    uint8 WrtDate[2];
+    uint16 FstClusLO;
+    uint32 FileSize;
+} STRUCT_PACKED;
+STRUCT_PACK_END
+
+#endif
diff --git a/sys/fs/fat/fat_filelib.c b/sys/fs/fat/fat_filelib.c
new file mode 100644
index 0000000..2c4a236
--- /dev/null
+++ b/sys/fs/fat/fat_filelib.c
@@ -0,0 +1,1603 @@
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//                            FAT16/32 File IO Library
+//                                    V2.6
+//                              Ultra-Embedded.com
+//                            Copyright 2003 - 2012
+//
+//                         Email: admin@ultra-embedded.com
+//
+//                                License: GPL
+//   If you would like a version with a more permissive license for use in
+//   closed source commercial applications please contact me for details.
+//-----------------------------------------------------------------------------
+//
+// This file is part of FAT File IO Library.
+//
+// FAT File IO Library is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// FAT File IO Library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FAT File IO Library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+#include 
+#include 
+#include "fat_defs.h"
+#include "fat_access.h"
+#include "fat_table.h"
+#include "fat_write.h"
+#include "fat_misc.h"
+#include "fat_string.h"
+#include "fat_filelib.h"
+#include "fat_cache.h"
+
+//-----------------------------------------------------------------------------
+// Locals
+//-----------------------------------------------------------------------------
+static FL_FILE            _files[FATFS_MAX_OPEN_FILES];
+static int                _filelib_init = 0;
+static int                _filelib_valid = 0;
+static struct fatfs       _fs;
+static struct fat_list    _open_file_list;
+static struct fat_list    _free_file_list;
+
+//-----------------------------------------------------------------------------
+// Macros
+//-----------------------------------------------------------------------------
+
+// Macro for checking if file lib is initialised
+#define CHECK_FL_INIT()     { if (_filelib_init==0) fl_init(); }
+
+#define FL_LOCK(a)          do { if ((a)->fl_lock) (a)->fl_lock(); } while (0)
+#define FL_UNLOCK(a)        do { if ((a)->fl_unlock) (a)->fl_unlock(); } while (0)
+
+//-----------------------------------------------------------------------------
+// Local Functions
+//-----------------------------------------------------------------------------
+static void                _fl_init();
+
+//-----------------------------------------------------------------------------
+// _allocate_file: Find a slot in the open files buffer for a new file
+//-----------------------------------------------------------------------------
+static FL_FILE* _allocate_file(void)
+{
+    // Allocate free file
+    struct fat_node *node = fat_list_pop_head(&_free_file_list);
+
+    // Add to open list
+    if (node)
+        fat_list_insert_last(&_open_file_list, node);
+
+    return fat_list_entry(node, FL_FILE, list_node);
+}
+//-----------------------------------------------------------------------------
+// _check_file_open: Returns true if the file is already open
+//-----------------------------------------------------------------------------
+static int _check_file_open(FL_FILE* file)
+{
+    struct fat_node *node;
+
+    // Compare open files
+    fat_list_for_each(&_open_file_list, node)
+    {
+        FL_FILE* openFile = fat_list_entry(node, FL_FILE, list_node);
+
+        // If not the current file
+        if (openFile != file)
+        {
+            // Compare path and name
+            if ( (fatfs_compare_names(openFile->path,file->path)) && (fatfs_compare_names(openFile->filename,file->filename)) )
+                return 1;
+        }
+    }
+
+    return 0;
+}
+//-----------------------------------------------------------------------------
+// _free_file: Free open file handle
+//-----------------------------------------------------------------------------
+static void _free_file(FL_FILE* file)
+{
+    // Remove from open list
+    fat_list_remove(&_open_file_list, &file->list_node);
+
+    // Add to free list
+    fat_list_insert_last(&_free_file_list, &file->list_node);
+}
+
+//-----------------------------------------------------------------------------
+//                                Low Level
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// _open_directory: Cycle through path string to find the start cluster
+// address of the highest subdir.
+//-----------------------------------------------------------------------------
+static int _open_directory(char *path, uint32 *pathCluster)
+{
+    int levels;
+    int sublevel;
+    char currentfolder[FATFS_MAX_LONG_FILENAME];
+    struct fat_dir_entry sfEntry;
+    uint32 startcluster;
+
+    // Set starting cluster to root cluster
+    startcluster = fatfs_get_root_cluster(&_fs);
+
+    // Find number of levels
+    levels = fatfs_total_path_levels(path);
+
+    // Cycle through each level and get the start sector
+    for (sublevel=0;sublevel<(levels+1);sublevel++)
+    {
+        if (fatfs_get_substring(path, sublevel, currentfolder, sizeof(currentfolder)) == -1)
+            return 0;
+
+        // Find clusteraddress for folder (currentfolder)
+        if (fatfs_get_file_entry(&_fs, startcluster, currentfolder,&sfEntry))
+        {
+            // Check entry is folder
+            if (fatfs_entry_is_dir(&sfEntry))
+                startcluster = ((FAT_HTONS((uint32)sfEntry.FstClusHI))<<16) + FAT_HTONS(sfEntry.FstClusLO);
+            else
+                return 0;
+        }
+        else
+            return 0;
+    }
+
+    *pathCluster = startcluster;
+    return 1;
+}
+//-----------------------------------------------------------------------------
+// _create_directory: Cycle through path string and create the end directory
+//-----------------------------------------------------------------------------
+#if FATFS_INC_WRITE_SUPPORT
+static int _create_directory(char *path)
+{
+    FL_FILE* file;
+    struct fat_dir_entry sfEntry;
+    char shortFilename[FAT_SFN_SIZE_FULL];
+    int tailNum = 0;
+    int i;
+
+    // Allocate a new file handle
+    file = _allocate_file();
+    if (!file)
+        return 0;
+
+    // Clear filename
+    memset(file->path, '\0', sizeof(file->path));
+    memset(file->filename, '\0', sizeof(file->filename));
+
+    // Split full path into filename and directory path
+    if (fatfs_split_path((char*)path, file->path, sizeof(file->path), file->filename, sizeof(file->filename)) == -1)
+    {
+        _free_file(file);
+        return 0;
+    }
+
+    // Check if file already open
+    if (_check_file_open(file))
+    {
+        _free_file(file);
+        return 0;
+    }
+
+    // If file is in the root dir
+    if (file->path[0] == 0)
+        file->parentcluster = fatfs_get_root_cluster(&_fs);
+    else
+    {
+        // Find parent directory start cluster
+        if (!_open_directory(file->path, &file->parentcluster))
+        {
+            _free_file(file);
+            return 0;
+        }
+    }
+
+    // Check if same filename exists in directory
+    if (fatfs_get_file_entry(&_fs, file->parentcluster, file->filename,&sfEntry) == 1)
+    {
+        _free_file(file);
+        return 0;
+    }
+
+    file->startcluster = 0;
+
+    // Create the file space for the folder (at least one clusters worth!)
+    if (!fatfs_allocate_free_space(&_fs, 1, &file->startcluster, 1))
+    {
+        _free_file(file);
+        return 0;
+    }
+
+    // Erase new directory cluster
+    memset(file->file_data_sector, 0x00, FAT_SECTOR_SIZE);
+    for (i=0;i<_fs.sectors_per_cluster;i++)
+    {
+        if (!fatfs_write_sector(&_fs, file->startcluster, i, file->file_data_sector))
+        {
+            _free_file(file);
+            return 0;
+        }
+    }
+
+#if FATFS_INC_LFN_SUPPORT
+
+    // Generate a short filename & tail
+    tailNum = 0;
+    do
+    {
+        // Create a standard short filename (without tail)
+        fatfs_lfn_create_sfn(shortFilename, file->filename);
+
+        // If second hit or more, generate a ~n tail
+        if (tailNum != 0)
+            fatfs_lfn_generate_tail((char*)file->shortfilename, shortFilename, tailNum);
+        // Try with no tail if first entry
+        else
+            memcpy(file->shortfilename, shortFilename, FAT_SFN_SIZE_FULL);
+
+        // Check if entry exists already or not
+        if (fatfs_sfn_exists(&_fs, file->parentcluster, (char*)file->shortfilename) == 0)
+            break;
+
+        tailNum++;
+    }
+    while (tailNum < 9999);
+
+    // We reached the max number of duplicate short file names (unlikely!)
+    if (tailNum == 9999)
+    {
+        // Delete allocated space
+        fatfs_free_cluster_chain(&_fs, file->startcluster);
+
+        _free_file(file);
+        return 0;
+    }
+#else
+    // Create a standard short filename (without tail)
+    if (!fatfs_lfn_create_sfn(shortFilename, file->filename))
+    {
+        // Delete allocated space
+        fatfs_free_cluster_chain(&_fs, file->startcluster);
+
+        _free_file(file);
+        return 0;
+    }
+
+    // Copy to SFN space
+    memcpy(file->shortfilename, shortFilename, FAT_SFN_SIZE_FULL);
+
+    // Check if entry exists already
+    if (fatfs_sfn_exists(&_fs, file->parentcluster, (char*)file->shortfilename))
+    {
+        // Delete allocated space
+        fatfs_free_cluster_chain(&_fs, file->startcluster);
+
+        _free_file(file);
+        return 0;
+    }
+#endif
+
+    // Add file to disk
+    if (!fatfs_add_file_entry(&_fs, file->parentcluster, (char*)file->filename, (char*)file->shortfilename, file->startcluster, 0, 1))
+    {
+        // Delete allocated space
+        fatfs_free_cluster_chain(&_fs, file->startcluster);
+
+        _free_file(file);
+        return 0;
+    }
+
+    // General
+    file->filelength = 0;
+    file->bytenum = 0;
+    file->file_data_address = 0xFFFFFFFF;
+    file->file_data_dirty = 0;
+    file->filelength_changed = 0;
+
+    // Quick lookup for next link in the chain
+    file->last_fat_lookup.ClusterIdx = 0xFFFFFFFF;
+    file->last_fat_lookup.CurrentCluster = 0xFFFFFFFF;
+
+    fatfs_fat_purge(&_fs);
+
+    _free_file(file);
+    return 1;
+}
+#endif
+//-----------------------------------------------------------------------------
+// _open_file: Open a file for reading
+//-----------------------------------------------------------------------------
+static FL_FILE* _open_file(const char *path)
+{
+    FL_FILE* file;
+    struct fat_dir_entry sfEntry;
+
+    // Allocate a new file handle
+    file = _allocate_file();
+    if (!file)
+        return NULL;
+
+    // Clear filename
+    memset(file->path, '\0', sizeof(file->path));
+    memset(file->filename, '\0', sizeof(file->filename));
+
+    // Split full path into filename and directory path
+    if (fatfs_split_path((char*)path, file->path, sizeof(file->path), file->filename, sizeof(file->filename)) == -1)
+    {
+        _free_file(file);
+        return NULL;
+    }
+
+    // Check if file already open
+    if (_check_file_open(file))
+    {
+        _free_file(file);
+        return NULL;
+    }
+
+    // If file is in the root dir
+    if (file->path[0]==0)
+        file->parentcluster = fatfs_get_root_cluster(&_fs);
+    else
+    {
+        // Find parent directory start cluster
+        if (!_open_directory(file->path, &file->parentcluster))
+        {
+            _free_file(file);
+            return NULL;
+        }
+    }
+
+    // Using dir cluster address search for filename
+    if (fatfs_get_file_entry(&_fs, file->parentcluster, file->filename,&sfEntry))
+        // Make sure entry is file not dir!
+        if (fatfs_entry_is_file(&sfEntry))
+        {
+            // Initialise file details
+            memcpy(file->shortfilename, sfEntry.Name, FAT_SFN_SIZE_FULL);
+            file->filelength = FAT_HTONL(sfEntry.FileSize);
+            file->bytenum = 0;
+            file->startcluster = ((FAT_HTONS((uint32)sfEntry.FstClusHI))<<16) + FAT_HTONS(sfEntry.FstClusLO);
+            file->file_data_address = 0xFFFFFFFF;
+            file->file_data_dirty = 0;
+            file->filelength_changed = 0;
+
+            // Quick lookup for next link in the chain
+            file->last_fat_lookup.ClusterIdx = 0xFFFFFFFF;
+            file->last_fat_lookup.CurrentCluster = 0xFFFFFFFF;
+
+            fatfs_cache_init(&_fs, file);
+
+            fatfs_fat_purge(&_fs);
+
+            return file;
+        }
+
+    _free_file(file);
+    return NULL;
+}
+//-----------------------------------------------------------------------------
+// _create_file: Create a new file
+//-----------------------------------------------------------------------------
+#if FATFS_INC_WRITE_SUPPORT
+static FL_FILE* _create_file(const char *filename)
+{
+    FL_FILE* file;
+    struct fat_dir_entry sfEntry;
+    char shortFilename[FAT_SFN_SIZE_FULL];
+    int tailNum = 0;
+
+    // No write access?
+    if (!_fs.disk_io.write_media)
+        return NULL;
+
+    // Allocate a new file handle
+    file = _allocate_file();
+    if (!file)
+        return NULL;
+
+    // Clear filename
+    memset(file->path, '\0', sizeof(file->path));
+    memset(file->filename, '\0', sizeof(file->filename));
+
+    // Split full path into filename and directory path
+    if (fatfs_split_path((char*)filename, file->path, sizeof(file->path), file->filename, sizeof(file->filename)) == -1)
+    {
+        _free_file(file);
+        return NULL;
+    }
+
+    // Check if file already open
+    if (_check_file_open(file))
+    {
+        _free_file(file);
+        return NULL;
+    }
+
+    // If file is in the root dir
+    if (file->path[0] == 0)
+        file->parentcluster = fatfs_get_root_cluster(&_fs);
+    else
+    {
+        // Find parent directory start cluster
+        if (!_open_directory(file->path, &file->parentcluster))
+        {
+            _free_file(file);
+            return NULL;
+        }
+    }
+
+    // Check if same filename exists in directory
+    if (fatfs_get_file_entry(&_fs, file->parentcluster, file->filename,&sfEntry) == 1)
+    {
+        _free_file(file);
+        return NULL;
+    }
+
+    file->startcluster = 0;
+
+    // Create the file space for the file (at least one clusters worth!)
+    if (!fatfs_allocate_free_space(&_fs, 1, &file->startcluster, 1))
+    {
+        _free_file(file);
+        return NULL;
+    }
+
+#if FATFS_INC_LFN_SUPPORT
+    // Generate a short filename & tail
+    tailNum = 0;
+    do
+    {
+        // Create a standard short filename (without tail)
+        fatfs_lfn_create_sfn(shortFilename, file->filename);
+
+        // If second hit or more, generate a ~n tail
+        if (tailNum != 0)
+            fatfs_lfn_generate_tail((char*)file->shortfilename, shortFilename, tailNum);
+        // Try with no tail if first entry
+        else
+            memcpy(file->shortfilename, shortFilename, FAT_SFN_SIZE_FULL);
+
+        // Check if entry exists already or not
+        if (fatfs_sfn_exists(&_fs, file->parentcluster, (char*)file->shortfilename) == 0)
+            break;
+
+        tailNum++;
+    }
+    while (tailNum < 9999);
+
+    // We reached the max number of duplicate short file names (unlikely!)
+    if (tailNum == 9999)
+    {
+        // Delete allocated space
+        fatfs_free_cluster_chain(&_fs, file->startcluster);
+
+        _free_file(file);
+        return NULL;
+    }
+#else
+    // Create a standard short filename (without tail)
+    if (!fatfs_lfn_create_sfn(shortFilename, file->filename))
+    {
+        // Delete allocated space
+        fatfs_free_cluster_chain(&_fs, file->startcluster);
+
+        _free_file(file);
+        return NULL;
+    }
+
+    // Copy to SFN space
+    memcpy(file->shortfilename, shortFilename, FAT_SFN_SIZE_FULL);
+
+    // Check if entry exists already
+    if (fatfs_sfn_exists(&_fs, file->parentcluster, (char*)file->shortfilename))
+    {
+        // Delete allocated space
+        fatfs_free_cluster_chain(&_fs, file->startcluster);
+
+        _free_file(file);
+        return NULL;
+    }
+#endif
+
+    // Add file to disk
+    if (!fatfs_add_file_entry(&_fs, file->parentcluster, (char*)file->filename, (char*)file->shortfilename, file->startcluster, 0, 0))
+    {
+        // Delete allocated space
+        fatfs_free_cluster_chain(&_fs, file->startcluster);
+
+        _free_file(file);
+        return NULL;
+    }
+
+    // General
+    file->filelength = 0;
+    file->bytenum = 0;
+    file->file_data_address = 0xFFFFFFFF;
+    file->file_data_dirty = 0;
+    file->filelength_changed = 0;
+
+    // Quick lookup for next link in the chain
+    file->last_fat_lookup.ClusterIdx = 0xFFFFFFFF;
+    file->last_fat_lookup.CurrentCluster = 0xFFFFFFFF;
+
+    fatfs_cache_init(&_fs, file);
+
+    fatfs_fat_purge(&_fs);
+
+    return file;
+}
+#endif
+//-----------------------------------------------------------------------------
+// _read_sectors: Read sector(s) from disk to file
+//-----------------------------------------------------------------------------
+static uint32 _read_sectors(FL_FILE* file, uint32 offset, uint8 *buffer, uint32 count)
+{
+    uint32 Sector = 0;
+    uint32 ClusterIdx = 0;
+    uint32 Cluster = 0;
+    uint32 i;
+    uint32 lba;
+
+    // Find cluster index within file & sector with cluster
+    ClusterIdx = offset / _fs.sectors_per_cluster;
+    Sector = offset - (ClusterIdx * _fs.sectors_per_cluster);
+
+    // Limit number of sectors read to the number remaining in this cluster
+    if ((Sector + count) > _fs.sectors_per_cluster)
+        count = _fs.sectors_per_cluster - Sector;
+
+    // Quick lookup for next link in the chain
+    if (ClusterIdx == file->last_fat_lookup.ClusterIdx)
+        Cluster = file->last_fat_lookup.CurrentCluster;
+    // Else walk the chain
+    else
+    {
+        // Starting from last recorded cluster?
+        if (ClusterIdx && ClusterIdx == file->last_fat_lookup.ClusterIdx + 1)
+        {
+            i = file->last_fat_lookup.ClusterIdx;
+            Cluster = file->last_fat_lookup.CurrentCluster;
+        }
+        // Start searching from the beginning..
+        else
+        {
+            // Set start of cluster chain to initial value
+            i = 0;
+            Cluster = file->startcluster;
+        }
+
+        // Follow chain to find cluster to read
+        for ( ;ilast_fat_lookup.CurrentCluster = Cluster;
+            file->last_fat_lookup.ClusterIdx = ClusterIdx;
+        }
+    }
+
+    // If end of cluster chain then return false
+    if (Cluster == FAT32_LAST_CLUSTER)
+        return 0;
+
+    // Calculate sector address
+    lba = fatfs_lba_of_cluster(&_fs, Cluster) + Sector;
+
+    // Read sector of file
+    if (fatfs_sector_read(&_fs, lba, buffer, count))
+        return count;
+    else
+        return 0;
+}
+
+//-----------------------------------------------------------------------------
+//                                External API
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// fl_init: Initialise library
+//-----------------------------------------------------------------------------
+void fl_init(void)
+{
+    int i;
+
+    fat_list_init(&_free_file_list);
+    fat_list_init(&_open_file_list);
+
+    // Add all file objects to free list
+    for (i=0;iflags = flags;
+
+    FL_UNLOCK(&_fs);
+    return file;
+}
+//-----------------------------------------------------------------------------
+// _write_sectors: Write sector(s) to disk
+//-----------------------------------------------------------------------------
+#if FATFS_INC_WRITE_SUPPORT
+static uint32 _write_sectors(FL_FILE* file, uint32 offset, uint8 *buf, uint32 count)
+{
+    uint32 SectorNumber = 0;
+    uint32 ClusterIdx = 0;
+    uint32 Cluster = 0;
+    uint32 LastCluster = FAT32_LAST_CLUSTER;
+    uint32 i;
+    uint32 lba;
+    uint32 TotalWriteCount = count;
+
+    // Find values for Cluster index & sector within cluster
+    ClusterIdx = offset / _fs.sectors_per_cluster;
+    SectorNumber = offset - (ClusterIdx * _fs.sectors_per_cluster);
+
+    // Limit number of sectors written to the number remaining in this cluster
+    if ((SectorNumber + count) > _fs.sectors_per_cluster)
+        count = _fs.sectors_per_cluster - SectorNumber;
+
+    // Quick lookup for next link in the chain
+    if (ClusterIdx == file->last_fat_lookup.ClusterIdx)
+        Cluster = file->last_fat_lookup.CurrentCluster;
+    // Else walk the chain
+    else
+    {
+        // Starting from last recorded cluster?
+        if (ClusterIdx && ClusterIdx == file->last_fat_lookup.ClusterIdx + 1)
+        {
+            i = file->last_fat_lookup.ClusterIdx;
+            Cluster = file->last_fat_lookup.CurrentCluster;
+        }
+        // Start searching from the beginning..
+        else
+        {
+            // Set start of cluster chain to initial value
+            i = 0;
+            Cluster = file->startcluster;
+        }
+
+        // Follow chain to find cluster to read
+        for ( ;ilast_fat_lookup.CurrentCluster = Cluster;
+        file->last_fat_lookup.ClusterIdx = ClusterIdx;
+    }
+
+    // Calculate write address
+    lba = fatfs_lba_of_cluster(&_fs, Cluster) + SectorNumber;
+
+    if (fatfs_sector_write(&_fs, lba, buf, count))
+        return count;
+    else
+        return 0;
+}
+#endif
+//-----------------------------------------------------------------------------
+// fl_fflush: Flush un-written data to the file
+//-----------------------------------------------------------------------------
+int fl_fflush(void *f)
+{
+#if FATFS_INC_WRITE_SUPPORT
+    FL_FILE *file = (FL_FILE *)f;
+
+    // If first call to library, initialise
+    CHECK_FL_INIT();
+
+    if (file)
+    {
+        FL_LOCK(&_fs);
+
+        // If some write data still in buffer
+        if (file->file_data_dirty)
+        {
+            // Write back current sector before loading next
+            if (_write_sectors(file, file->file_data_address, file->file_data_sector, 1))
+                file->file_data_dirty = 0;
+        }
+
+        FL_UNLOCK(&_fs);
+    }
+#endif
+    return 0;
+}
+//-----------------------------------------------------------------------------
+// fl_fclose: Close an open file
+//-----------------------------------------------------------------------------
+void fl_fclose(void *f)
+{
+    FL_FILE *file = (FL_FILE *)f;
+
+    // If first call to library, initialise
+    CHECK_FL_INIT();
+
+    if (file)
+    {
+        FL_LOCK(&_fs);
+
+        // Flush un-written data to file
+        fl_fflush(f);
+
+        // File size changed?
+        if (file->filelength_changed)
+        {
+#if FATFS_INC_WRITE_SUPPORT
+            // Update filesize in directory
+            fatfs_update_file_length(&_fs, file->parentcluster, (char*)file->shortfilename, file->filelength);
+#endif
+            file->filelength_changed = 0;
+        }
+
+        file->bytenum = 0;
+        file->filelength = 0;
+        file->startcluster = 0;
+        file->file_data_address = 0xFFFFFFFF;
+        file->file_data_dirty = 0;
+        file->filelength_changed = 0;
+
+        // Free file handle
+        _free_file(file);
+
+        fatfs_fat_purge(&_fs);
+
+        FL_UNLOCK(&_fs);
+    }
+}
+//-----------------------------------------------------------------------------
+// fl_fgetc: Get a character in the stream
+//-----------------------------------------------------------------------------
+int fl_fgetc(void *f)
+{
+    int res;
+    uint8 data = 0;
+
+    res = fl_fread(&data, 1, 1, f);
+    if (res == 1)
+        return (int)data;
+    else
+        return res;
+}
+//-----------------------------------------------------------------------------
+// fl_fgets: Get a string from a stream
+//-----------------------------------------------------------------------------
+char *fl_fgets(char *s, int n, void *f)
+{
+    int idx = 0;
+
+    // Space for null terminator?
+    if (n > 0)
+    {
+        // While space (+space for null terminator)
+        while (idx < (n-1))
+        {
+            int ch = fl_fgetc(f);
+
+            // EOF / Error?
+            if (ch < 0)
+                break;
+
+            // Store character read from stream
+            s[idx++] = (char)ch;
+
+            // End of line?
+            if (ch == '\n')
+                break;
+        }
+
+        if (idx > 0)
+            s[idx] = '\0';
+    }
+
+    return (idx > 0) ? s : 0;
+}
+//-----------------------------------------------------------------------------
+// fl_fread: Read a block of data from the file
+//-----------------------------------------------------------------------------
+int fl_fread(void * buffer, int size, int length, void *f )
+{
+    uint32 sector;
+    uint32 offset;
+    int copyCount;
+    int count = size * length;
+    int bytesRead = 0;
+
+    FL_FILE *file = (FL_FILE *)f;
+
+    // If first call to library, initialise
+    CHECK_FL_INIT();
+
+    if (buffer==NULL || file==NULL)
+        return -1;
+
+    // No read permissions
+    if (!(file->flags & FILE_READ))
+        return -1;
+
+    // Nothing to be done
+    if (!count)
+        return 0;
+
+    // Check if read starts past end of file
+    if (file->bytenum >= file->filelength)
+        return -1;
+
+    // Limit to file size
+    if ( (file->bytenum + count) > file->filelength )
+        count = file->filelength - file->bytenum;
+
+    // Calculate start sector
+    sector = file->bytenum / FAT_SECTOR_SIZE;
+
+    // Offset to start copying data from first sector
+    offset = file->bytenum % FAT_SECTOR_SIZE;
+
+    while (bytesRead < count)
+    {
+        // Read whole sector, read from media directly into target buffer
+        if ((offset == 0) && ((count - bytesRead) >= FAT_SECTOR_SIZE))
+        {
+            // Read as many sectors as possible into target buffer
+            uint32 sectorsRead = _read_sectors(file, sector, (uint8*)((uint8*)buffer + bytesRead), (count - bytesRead) / FAT_SECTOR_SIZE);
+            if (sectorsRead)
+            {
+                // We have upto one sector to copy
+                copyCount = FAT_SECTOR_SIZE * sectorsRead;
+
+                // Move onto next sector and reset copy offset
+                sector+= sectorsRead;
+                offset = 0;
+            }
+            else
+                break;
+        }
+        else
+        {
+            // Do we need to re-read the sector?
+            if (file->file_data_address != sector)
+            {
+                // Flush un-written data to file
+                if (file->file_data_dirty)
+                    fl_fflush(file);
+
+                // Get LBA of sector offset within file
+                if (!_read_sectors(file, sector, file->file_data_sector, 1))
+                    // Read failed - out of range (probably)
+                    break;
+
+                file->file_data_address = sector;
+                file->file_data_dirty = 0;
+            }
+
+            // We have upto one sector to copy
+            copyCount = FAT_SECTOR_SIZE - offset;
+
+            // Only require some of this sector?
+            if (copyCount > (count - bytesRead))
+                copyCount = (count - bytesRead);
+
+            // Copy to application buffer
+            memcpy( (uint8*)((uint8*)buffer + bytesRead), (uint8*)(file->file_data_sector + offset), copyCount);
+
+            // Move onto next sector and reset copy offset
+            sector++;
+            offset = 0;
+        }
+
+        // Increase total read count
+        bytesRead += copyCount;
+
+        // Increment file pointer
+        file->bytenum += copyCount;
+    }
+
+    return bytesRead;
+}
+//-----------------------------------------------------------------------------
+// fl_fseek: Seek to a specific place in the file
+//-----------------------------------------------------------------------------
+int fl_fseek( void *f, long offset, int origin )
+{
+    FL_FILE *file = (FL_FILE *)f;
+    int res = -1;
+
+    // If first call to library, initialise
+    CHECK_FL_INIT();
+
+    if (!file)
+        return -1;
+
+    if (origin == SEEK_END && offset != 0)
+        return -1;
+
+    FL_LOCK(&_fs);
+
+    // Invalidate file buffer
+    file->file_data_address = 0xFFFFFFFF;
+    file->file_data_dirty = 0;
+
+    if (origin == SEEK_SET)
+    {
+        file->bytenum = (uint32)offset;
+
+        if (file->bytenum > file->filelength)
+            file->bytenum = file->filelength;
+
+        res = 0;
+    }
+    else if (origin == SEEK_CUR)
+    {
+        // Positive shift
+        if (offset >= 0)
+        {
+            file->bytenum += offset;
+
+            if (file->bytenum > file->filelength)
+                file->bytenum = file->filelength;
+        }
+        // Negative shift
+        else
+        {
+            // Make shift positive
+            offset = -offset;
+
+            // Limit to negative shift to start of file
+            if ((uint32)offset > file->bytenum)
+                file->bytenum = 0;
+            else
+                file->bytenum-= offset;
+        }
+
+        res = 0;
+    }
+    else if (origin == SEEK_END)
+    {
+        file->bytenum = file->filelength;
+        res = 0;
+    }
+    else
+        res = -1;
+
+    FL_UNLOCK(&_fs);
+
+    return res;
+}
+//-----------------------------------------------------------------------------
+// fl_fgetpos: Get the current file position
+//-----------------------------------------------------------------------------
+int fl_fgetpos(void *f , uint32 * position)
+{
+    FL_FILE *file = (FL_FILE *)f;
+
+    if (!file)
+        return -1;
+
+    FL_LOCK(&_fs);
+
+    // Get position
+    *position = file->bytenum;
+
+    FL_UNLOCK(&_fs);
+
+    return 0;
+}
+//-----------------------------------------------------------------------------
+// fl_ftell: Get the current file position
+//-----------------------------------------------------------------------------
+long fl_ftell(void *f)
+{
+    uint32 pos = 0;
+
+    fl_fgetpos(f, &pos);
+
+    return (long)pos;
+}
+//-----------------------------------------------------------------------------
+// fl_feof: Is the file pointer at the end of the stream?
+//-----------------------------------------------------------------------------
+int fl_feof(void *f)
+{
+    FL_FILE *file = (FL_FILE *)f;
+    int res;
+
+    if (!file)
+        return -1;
+
+    FL_LOCK(&_fs);
+
+    if (file->bytenum == file->filelength)
+        res = EOF;
+    else
+        res = 0;
+
+    FL_UNLOCK(&_fs);
+
+    return res;
+}
+//-----------------------------------------------------------------------------
+// fl_fputc: Write a character to the stream
+//-----------------------------------------------------------------------------
+#if FATFS_INC_WRITE_SUPPORT
+int fl_fputc(int c, void *f)
+{
+    uint8 data = (uint8)c;
+    int res;
+
+    res = fl_fwrite(&data, 1, 1, f);
+    if (res == 1)
+        return c;
+    else
+        return res;
+}
+#endif
+//-----------------------------------------------------------------------------
+// fl_fwrite: Write a block of data to the stream
+//-----------------------------------------------------------------------------
+#if FATFS_INC_WRITE_SUPPORT
+int fl_fwrite(const void * data, int size, int count, void *f )
+{
+    FL_FILE *file = (FL_FILE *)f;
+    uint32 sector;
+    uint32 offset;
+    uint32 length = (size*count);
+    uint8 *buffer = (uint8 *)data;
+    uint32 bytesWritten = 0;
+    uint32 copyCount;
+
+    // If first call to library, initialise
+    CHECK_FL_INIT();
+
+    if (!file)
+        return -1;
+
+    FL_LOCK(&_fs);
+
+    // No write permissions
+    if (!(file->flags & FILE_WRITE))
+    {
+        FL_UNLOCK(&_fs);
+        return -1;
+    }
+
+    // Append writes to end of file
+    if (file->flags & FILE_APPEND)
+        file->bytenum = file->filelength;
+    // Else write to current position
+
+    // Calculate start sector
+    sector = file->bytenum / FAT_SECTOR_SIZE;
+
+    // Offset to start copying data from first sector
+    offset = file->bytenum % FAT_SECTOR_SIZE;
+
+    while (bytesWritten < length)
+    {
+        // Whole sector or more to be written?
+        if ((offset == 0) && ((length - bytesWritten) >= FAT_SECTOR_SIZE))
+        {
+            uint32 sectorsWrote;
+
+            // Buffered sector, flush back to disk
+            if (file->file_data_address != 0xFFFFFFFF)
+            {
+                // Flush un-written data to file
+                if (file->file_data_dirty)
+                    fl_fflush(file);
+
+                file->file_data_address = 0xFFFFFFFF;
+                file->file_data_dirty = 0;
+            }
+
+            // Write as many sectors as possible
+            sectorsWrote = _write_sectors(file, sector, (uint8*)(buffer + bytesWritten), (length - bytesWritten) / FAT_SECTOR_SIZE);
+            copyCount = FAT_SECTOR_SIZE * sectorsWrote;
+
+            // Increase total read count
+            bytesWritten += copyCount;
+
+            // Increment file pointer
+            file->bytenum += copyCount;
+
+            // Move onto next sector and reset copy offset
+            sector+= sectorsWrote;
+            offset = 0;
+
+            if (!sectorsWrote)
+                break;
+        }
+        else
+        {
+            // We have upto one sector to copy
+            copyCount = FAT_SECTOR_SIZE - offset;
+
+            // Only require some of this sector?
+            if (copyCount > (length - bytesWritten))
+                copyCount = (length - bytesWritten);
+
+            // Do we need to read a new sector?
+            if (file->file_data_address != sector)
+            {
+                // Flush un-written data to file
+                if (file->file_data_dirty)
+                    fl_fflush(file);
+
+                // If we plan to overwrite the whole sector, we don't need to read it first!
+                if (copyCount != FAT_SECTOR_SIZE)
+                {
+                    // NOTE: This does not have succeed; if last sector of file
+                    // reached, no valid data will be read in, but write will
+                    // allocate some more space for new data.
+
+                    // Get LBA of sector offset within file
+                    if (!_read_sectors(file, sector, file->file_data_sector, 1))
+                        memset(file->file_data_sector, 0x00, FAT_SECTOR_SIZE);
+                }
+
+                file->file_data_address = sector;
+                file->file_data_dirty = 0;
+            }
+
+            // Copy from application buffer into sector buffer
+            memcpy((uint8*)(file->file_data_sector + offset), (uint8*)(buffer + bytesWritten), copyCount);
+
+            // Mark buffer as dirty
+            file->file_data_dirty = 1;
+
+            // Increase total read count
+            bytesWritten += copyCount;
+
+            // Increment file pointer
+            file->bytenum += copyCount;
+
+            // Move onto next sector and reset copy offset
+            sector++;
+            offset = 0;
+        }
+    }
+
+    // Write increased extent of the file?
+    if (file->bytenum > file->filelength)
+    {
+        // Increase file size to new point
+        file->filelength = file->bytenum;
+
+        // We are changing the file length and this
+        // will need to be writen back at some point
+        file->filelength_changed = 1;
+    }
+
+#if FATFS_INC_TIME_DATE_SUPPORT
+    // If time & date support is enabled, always force directory entry to be
+    // written in-order to update file modify / access time & date.
+    file->filelength_changed = 1;
+#endif
+
+    FL_UNLOCK(&_fs);
+
+    return (size*count);
+}
+#endif
+//-----------------------------------------------------------------------------
+// fl_fputs: Write a character string to the stream
+//-----------------------------------------------------------------------------
+#if FATFS_INC_WRITE_SUPPORT
+int fl_fputs(const char * str, void *f)
+{
+    int len = (int)strlen(str);
+    int res = fl_fwrite(str, 1, len, f);
+
+    if (res == len)
+        return len;
+    else
+        return res;
+}
+#endif
+//-----------------------------------------------------------------------------
+// fl_remove: Remove a file from the filesystem
+//-----------------------------------------------------------------------------
+#if FATFS_INC_WRITE_SUPPORT
+int fl_remove( const char * filename )
+{
+    FL_FILE* file;
+    int res = -1;
+
+    FL_LOCK(&_fs);
+
+    // Use read_file as this will check if the file is already open!
+    file = fl_fopen((char*)filename, "r");
+    if (file)
+    {
+        // Delete allocated space
+        if (fatfs_free_cluster_chain(&_fs, file->startcluster))
+        {
+            // Remove directory entries
+            if (fatfs_mark_file_deleted(&_fs, file->parentcluster, (char*)file->shortfilename))
+            {
+                // Close the file handle (this should not write anything to the file
+                // as we have not changed the file since opening it!)
+                fl_fclose(file);
+
+                res = 0;
+            }
+        }
+    }
+
+    FL_UNLOCK(&_fs);
+
+    return res;
+}
+#endif
+//-----------------------------------------------------------------------------
+// fl_createdirectory: Create a directory based on a path
+//-----------------------------------------------------------------------------
+#if FATFS_INC_WRITE_SUPPORT
+int fl_createdirectory(const char *path)
+{
+    int res;
+
+    // If first call to library, initialise
+    CHECK_FL_INIT();
+
+    FL_LOCK(&_fs);
+    res =_create_directory((char*)path);
+    FL_UNLOCK(&_fs);
+
+    return res;
+}
+#endif
+//-----------------------------------------------------------------------------
+// fl_listdirectory: List a directory based on a path
+//-----------------------------------------------------------------------------
+#if FATFS_DIR_LIST_SUPPORT
+void fl_listdirectory(const char *path)
+{
+    FL_DIR dirstat;
+
+    // If first call to library, initialise
+    CHECK_FL_INIT();
+
+    FL_LOCK(&_fs);
+
+    FAT_PRINTF(("\r\nDirectory %s\r\n", path));
+
+    if (fl_opendir(path, &dirstat))
+    {
+        struct fs_dir_ent dirent;
+
+        while (fl_readdir(&dirstat, &dirent) == 0)
+        {
+#if FATFS_INC_TIME_DATE_SUPPORT
+            int d,m,y,h,mn,s;
+            fatfs_convert_from_fat_time(dirent.write_time, &h,&m,&s);
+            fatfs_convert_from_fat_date(dirent.write_date, &d,&mn,&y);
+            FAT_PRINTF(("%02d/%02d/%04d  %02d:%02d      ", d,mn,y,h,m));
+#endif
+
+            if (dirent.is_dir)
+            {
+                FAT_PRINTF(("%s \r\n", dirent.filename));
+            }
+            else
+            {
+                FAT_PRINTF(("%s [%d bytes]\r\n", dirent.filename, dirent.size));
+            }
+        }
+
+        fl_closedir(&dirstat);
+    }
+
+    FL_UNLOCK(&_fs);
+}
+#endif
+//-----------------------------------------------------------------------------
+// fl_opendir: Opens a directory for listing
+//-----------------------------------------------------------------------------
+#if FATFS_DIR_LIST_SUPPORT
+FL_DIR* fl_opendir(const char* path, FL_DIR *dir)
+{
+    int levels;
+    int res = 1;
+    uint32 cluster = FAT32_INVALID_CLUSTER;
+
+    // If first call to library, initialise
+    CHECK_FL_INIT();
+
+    FL_LOCK(&_fs);
+
+    levels = fatfs_total_path_levels((char*)path) + 1;
+
+    // If path is in the root dir
+    if (levels == 0)
+        cluster = fatfs_get_root_cluster(&_fs);
+    // Find parent directory start cluster
+    else
+        res = _open_directory((char*)path, &cluster);
+
+    if (res)
+        fatfs_list_directory_start(&_fs, dir, cluster);
+
+    FL_UNLOCK(&_fs);
+
+    return cluster != FAT32_INVALID_CLUSTER ? dir : 0;
+}
+#endif
+//-----------------------------------------------------------------------------
+// fl_readdir: Get next item in directory
+//-----------------------------------------------------------------------------
+#if FATFS_DIR_LIST_SUPPORT
+int fl_readdir(FL_DIR *dirls, fl_dirent *entry)
+{
+    int res = 0;
+
+    // If first call to library, initialise
+    CHECK_FL_INIT();
+
+    FL_LOCK(&_fs);
+
+    res = fatfs_list_directory_next(&_fs, dirls, entry);
+
+    FL_UNLOCK(&_fs);
+
+    return res ? 0 : -1;
+}
+#endif
+//-----------------------------------------------------------------------------
+// fl_closedir: Close directory after listing
+//-----------------------------------------------------------------------------
+#if FATFS_DIR_LIST_SUPPORT
+int fl_closedir(FL_DIR* dir)
+{
+    // Not used
+    return 0;
+}
+#endif
+//-----------------------------------------------------------------------------
+// fl_is_dir: Is this a directory?
+//-----------------------------------------------------------------------------
+#if FATFS_DIR_LIST_SUPPORT
+int fl_is_dir(const char *path)
+{
+    int res = 0;
+    FL_DIR dir;
+
+    if (fl_opendir(path, &dir))
+    {
+        res = 1;
+        fl_closedir(&dir);
+    }
+
+    return res;
+}
+#endif
+//-----------------------------------------------------------------------------
+// fl_format: Format a partition with either FAT16 or FAT32 based on size
+//-----------------------------------------------------------------------------
+#if FATFS_INC_FORMAT_SUPPORT
+int fl_format(uint32 volume_sectors, const char *name)
+{
+    return fatfs_format(&_fs, volume_sectors, name);
+}
+#endif /*FATFS_INC_FORMAT_SUPPORT*/
+//-----------------------------------------------------------------------------
+// fl_get_fs:
+//-----------------------------------------------------------------------------
+#ifdef FATFS_INC_TEST_HOOKS
+struct fatfs* fl_get_fs(void)
+{
+    return &_fs;
+}
+#endif
diff --git a/sys/fs/fat/fat_filelib.h b/sys/fs/fat/fat_filelib.h
new file mode 100644
index 0000000..a40a28f
--- /dev/null
+++ b/sys/fs/fat/fat_filelib.h
@@ -0,0 +1,146 @@
+#ifndef __FAT_FILELIB_H__
+#define __FAT_FILELIB_H__
+
+#include "fat_opts.h"
+#include "fat_access.h"
+#include "fat_list.h"
+
+//-----------------------------------------------------------------------------
+// Defines
+//-----------------------------------------------------------------------------
+#ifndef SEEK_CUR
+    #define SEEK_CUR    1
+#endif
+
+#ifndef SEEK_END
+    #define SEEK_END    2
+#endif
+
+#ifndef SEEK_SET
+    #define SEEK_SET    0
+#endif
+
+#ifndef EOF
+    #define EOF         (-1)
+#endif
+
+//-----------------------------------------------------------------------------
+// Structures
+//-----------------------------------------------------------------------------
+struct sFL_FILE;
+
+struct cluster_lookup
+{
+    uint32 ClusterIdx;
+    uint32 CurrentCluster;
+};
+
+typedef struct sFL_FILE
+{
+    uint32                  parentcluster;
+    uint32                  startcluster;
+    uint32                  bytenum;
+    uint32                  filelength;
+    int                     filelength_changed;
+    char                    path[FATFS_MAX_LONG_FILENAME];
+    char                    filename[FATFS_MAX_LONG_FILENAME];
+    uint8                   shortfilename[11];
+
+#ifdef FAT_CLUSTER_CACHE_ENTRIES
+    uint32                  cluster_cache_idx[FAT_CLUSTER_CACHE_ENTRIES];
+    uint32                  cluster_cache_data[FAT_CLUSTER_CACHE_ENTRIES];
+#endif
+
+    // Cluster Lookup
+    struct cluster_lookup   last_fat_lookup;
+
+    // Read/Write sector buffer
+    uint8                   file_data_sector[FAT_SECTOR_SIZE];
+    uint32                  file_data_address;
+    int                     file_data_dirty;
+
+    // File fopen flags
+    uint8                   flags;
+#define FILE_READ           (1 << 0)
+#define FILE_WRITE          (1 << 1)
+#define FILE_APPEND         (1 << 2)
+#define FILE_BINARY         (1 << 3)
+#define FILE_ERASE          (1 << 4)
+#define FILE_CREATE         (1 << 5)
+
+    struct fat_node         list_node;
+} FL_FILE;
+
+//-----------------------------------------------------------------------------
+// Prototypes
+//-----------------------------------------------------------------------------
+
+// External
+void                fl_init(void);
+void                fl_attach_locks(void (*lock)(void), void (*unlock)(void));
+int                 fl_attach_media(fn_diskio_read rd, fn_diskio_write wr);
+void                fl_shutdown(void);
+
+// Standard API
+void*               fl_fopen(const char *path, const char *modifiers);
+void                fl_fclose(void *file);
+int                 fl_fflush(void *file);
+int                 fl_fgetc(void *file);
+char *              fl_fgets(char *s, int n, void *f);
+int                 fl_fputc(int c, void *file);
+int                 fl_fputs(const char * str, void *file);
+int                 fl_fwrite(const void * data, int size, int count, void *file );
+int                 fl_fread(void * data, int size, int count, void *file );
+int                 fl_fseek(void *file , long offset , int origin );
+int                 fl_fgetpos(void *file , uint32 * position);
+long                fl_ftell(void *f);
+int                 fl_feof(void *f);
+int                 fl_remove(const char * filename);
+
+// Equivelant dirent.h
+typedef struct fs_dir_list_status    FL_DIR;
+typedef struct fs_dir_ent            fl_dirent;
+
+FL_DIR*             fl_opendir(const char* path, FL_DIR *dir);
+int                 fl_readdir(FL_DIR *dirls, fl_dirent *entry);
+int                 fl_closedir(FL_DIR* dir);
+
+// Extensions
+void                fl_listdirectory(const char *path);
+int                 fl_createdirectory(const char *path);
+int                 fl_is_dir(const char *path);
+
+int                 fl_format(uint32 volume_sectors, const char *name);
+
+// Test hooks
+#ifdef FATFS_INC_TEST_HOOKS
+struct fatfs*       fl_get_fs(void);
+#endif
+
+//-----------------------------------------------------------------------------
+// Stdio file I/O names
+//-----------------------------------------------------------------------------
+#ifdef USE_FILELIB_STDIO_COMPAT_NAMES
+
+#define FILE            FL_FILE
+
+#define fopen(a,b)      fl_fopen(a, b)
+#define fclose(a)       fl_fclose(a)
+#define fflush(a)       fl_fflush(a)
+#define fgetc(a)        fl_fgetc(a)
+#define fgets(a,b,c)    fl_fgets(a, b, c)
+#define fputc(a,b)      fl_fputc(a, b)
+#define fputs(a,b)      fl_fputs(a, b)
+#define fwrite(a,b,c,d) fl_fwrite(a, b, c, d)
+#define fread(a,b,c,d)  fl_fread(a, b, c, d)
+#define fseek(a,b,c)    fl_fseek(a, b, c)
+#define fgetpos(a,b)    fl_fgetpos(a, b)
+#define ftell(a)        fl_ftell(a)
+#define feof(a)         fl_feof(a)
+#define remove(a)       fl_remove(a)
+#define mkdir(a)        fl_createdirectory(a)
+#define rmdir(a)        0
+
+#endif
+
+#endif
diff --git a/sys/fs/fat/fat_format.c b/sys/fs/fat/fat_format.c
new file mode 100644
index 0000000..d067f37
--- /dev/null
+++ b/sys/fs/fat/fat_format.c
@@ -0,0 +1,532 @@
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//                            FAT16/32 File IO Library
+//                                    V2.6
+//                              Ultra-Embedded.com
+//                            Copyright 2003 - 2012
+//
+//                         Email: admin@ultra-embedded.com
+//
+//                                License: GPL
+//   If you would like a version with a more permissive license for use in
+//   closed source commercial applications please contact me for details.
+//-----------------------------------------------------------------------------
+//
+// This file is part of FAT File IO Library.
+//
+// FAT File IO Library is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// FAT File IO Library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FAT File IO Library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+#include 
+#include "fat_defs.h"
+#include "fat_access.h"
+#include "fat_table.h"
+#include "fat_write.h"
+#include "fat_string.h"
+#include "fat_misc.h"
+#include "fat_format.h"
+
+#if FATFS_INC_FORMAT_SUPPORT
+
+//-----------------------------------------------------------------------------
+// Tables
+//-----------------------------------------------------------------------------
+struct sec_per_clus_table
+{
+    uint32  sectors;
+    uint8   sectors_per_cluster;
+};
+
+struct sec_per_clus_table _cluster_size_table16[] =
+{
+    { 32680, 2},    // 16MB - 1K
+    { 262144, 4},   // 128MB - 2K
+    { 524288, 8},   // 256MB - 4K
+    { 1048576, 16}, // 512MB - 8K
+    { 2097152, 32}, // 1GB - 16K
+    { 4194304, 64}, // 2GB - 32K
+    { 8388608, 128},// 2GB - 64K [Warning only supported by Windows XP onwards]
+    { 0 , 0 }       // Invalid
+};
+
+struct sec_per_clus_table _cluster_size_table32[] =
+{
+    { 532480, 1},     // 260MB - 512b
+    { 16777216, 8},   // 8GB - 4K
+    { 33554432, 16},  // 16GB - 8K
+    { 67108864, 32},  // 32GB - 16K
+    { 0xFFFFFFFF, 64},// >32GB - 32K
+    { 0 , 0 }         // Invalid
+};
+
+//-----------------------------------------------------------------------------
+// fatfs_calc_cluster_size: Calculate what cluster size should be used
+//-----------------------------------------------------------------------------
+static uint8 fatfs_calc_cluster_size(uint32 sectors, int is_fat32)
+{
+    int i;
+
+    if (!is_fat32)
+    {
+        for (i=0; _cluster_size_table16[i].sectors_per_cluster != 0;i++)
+            if (sectors <= _cluster_size_table16[i].sectors)
+                return _cluster_size_table16[i].sectors_per_cluster;
+    }
+    else
+    {
+        for (i=0; _cluster_size_table32[i].sectors_per_cluster != 0;i++)
+            if (sectors <= _cluster_size_table32[i].sectors)
+                return _cluster_size_table32[i].sectors_per_cluster;
+    }
+
+    return 0;
+}
+//-----------------------------------------------------------------------------
+// fatfs_erase_sectors: Erase a number of sectors
+//-----------------------------------------------------------------------------
+static int fatfs_erase_sectors(struct fatfs *fs, uint32 lba, int count)
+{
+    int i;
+
+    // Zero sector first
+    memset(fs->currentsector.sector, 0, FAT_SECTOR_SIZE);
+
+    for (i=0;idisk_io.write_media(lba + i, fs->currentsector.sector, 1))
+            return 0;
+
+    return 1;
+}
+//-----------------------------------------------------------------------------
+// fatfs_create_boot_sector: Create the boot sector
+//-----------------------------------------------------------------------------
+static int fatfs_create_boot_sector(struct fatfs *fs, uint32 boot_sector_lba, uint32 vol_sectors, const char *name, int is_fat32)
+{
+    uint32 total_clusters;
+    int i;
+
+    // Zero sector initially
+    memset(fs->currentsector.sector, 0, FAT_SECTOR_SIZE);
+
+    // OEM Name & Jump Code
+    fs->currentsector.sector[0] = 0xEB;
+    fs->currentsector.sector[1] = 0x3C;
+    fs->currentsector.sector[2] = 0x90;
+    fs->currentsector.sector[3] = 0x4D;
+    fs->currentsector.sector[4] = 0x53;
+    fs->currentsector.sector[5] = 0x44;
+    fs->currentsector.sector[6] = 0x4F;
+    fs->currentsector.sector[7] = 0x53;
+    fs->currentsector.sector[8] = 0x35;
+    fs->currentsector.sector[9] = 0x2E;
+    fs->currentsector.sector[10] = 0x30;
+
+    // Bytes per sector
+    fs->currentsector.sector[11] = (FAT_SECTOR_SIZE >> 0) & 0xFF;
+    fs->currentsector.sector[12] = (FAT_SECTOR_SIZE >> 8) & 0xFF;
+
+    // Get sectors per cluster size for the disk
+    fs->sectors_per_cluster = fatfs_calc_cluster_size(vol_sectors, is_fat32);
+    if (!fs->sectors_per_cluster)
+        return 0; // Invalid disk size
+
+    // Sectors per cluster
+    fs->currentsector.sector[13] = fs->sectors_per_cluster;
+
+    // Reserved Sectors
+    if (!is_fat32)
+        fs->reserved_sectors = 8;
+    else
+        fs->reserved_sectors = 32;
+    fs->currentsector.sector[14] = (fs->reserved_sectors >> 0) & 0xFF;
+    fs->currentsector.sector[15] = (fs->reserved_sectors >> 8) & 0xFF;
+
+    // Number of FATS
+    fs->num_of_fats = 2;
+    fs->currentsector.sector[16] = fs->num_of_fats;
+
+    // Max entries in root dir (FAT16 only)
+    if (!is_fat32)
+    {
+        fs->root_entry_count = 512;
+        fs->currentsector.sector[17] = (fs->root_entry_count >> 0) & 0xFF;
+        fs->currentsector.sector[18] = (fs->root_entry_count >> 8) & 0xFF;
+    }
+    else
+    {
+        fs->root_entry_count = 0;
+        fs->currentsector.sector[17] = 0;
+        fs->currentsector.sector[18] = 0;
+    }
+
+    // [FAT16] Total sectors (use FAT32 count instead)
+    fs->currentsector.sector[19] = 0x00;
+    fs->currentsector.sector[20] = 0x00;
+
+    // Media type
+    fs->currentsector.sector[21] = 0xF8;
+
+
+    // FAT16 BS Details
+    if (!is_fat32)
+    {
+        // Count of sectors used by the FAT table (FAT16 only)
+        total_clusters = (vol_sectors / fs->sectors_per_cluster) + 1;
+        fs->fat_sectors = (total_clusters/(FAT_SECTOR_SIZE/2)) + 1;
+        fs->currentsector.sector[22] = (uint8)((fs->fat_sectors >> 0) & 0xFF);
+        fs->currentsector.sector[23] = (uint8)((fs->fat_sectors >> 8) & 0xFF);
+
+        // Sectors per track
+        fs->currentsector.sector[24] = 0x00;
+        fs->currentsector.sector[25] = 0x00;
+
+        // Heads
+        fs->currentsector.sector[26] = 0x00;
+        fs->currentsector.sector[27] = 0x00;
+
+        // Hidden sectors
+        fs->currentsector.sector[28] = 0x20;
+        fs->currentsector.sector[29] = 0x00;
+        fs->currentsector.sector[30] = 0x00;
+        fs->currentsector.sector[31] = 0x00;
+
+        // Total sectors for this volume
+        fs->currentsector.sector[32] = (uint8)((vol_sectors>>0)&0xFF);
+        fs->currentsector.sector[33] = (uint8)((vol_sectors>>8)&0xFF);
+        fs->currentsector.sector[34] = (uint8)((vol_sectors>>16)&0xFF);
+        fs->currentsector.sector[35] = (uint8)((vol_sectors>>24)&0xFF);
+
+        // Drive number
+        fs->currentsector.sector[36] = 0x00;
+
+        // Reserved
+        fs->currentsector.sector[37] = 0x00;
+
+        // Boot signature
+        fs->currentsector.sector[38] = 0x29;
+
+        // Volume ID
+        fs->currentsector.sector[39] = 0x12;
+        fs->currentsector.sector[40] = 0x34;
+        fs->currentsector.sector[41] = 0x56;
+        fs->currentsector.sector[42] = 0x78;
+
+        // Volume name
+        for (i=0;i<11;i++)
+        {
+            if (i < (int)strlen(name))
+                fs->currentsector.sector[i+43] = name[i];
+            else
+                fs->currentsector.sector[i+43] = ' ';
+        }
+
+        // File sys type
+        fs->currentsector.sector[54] = 'F';
+        fs->currentsector.sector[55] = 'A';
+        fs->currentsector.sector[56] = 'T';
+        fs->currentsector.sector[57] = '1';
+        fs->currentsector.sector[58] = '6';
+        fs->currentsector.sector[59] = ' ';
+        fs->currentsector.sector[60] = ' ';
+        fs->currentsector.sector[61] = ' ';
+
+        // Signature
+        fs->currentsector.sector[510] = 0x55;
+        fs->currentsector.sector[511] = 0xAA;
+    }
+    // FAT32 BS Details
+    else
+    {
+        // Count of sectors used by the FAT table (FAT16 only)
+        fs->currentsector.sector[22] = 0;
+        fs->currentsector.sector[23] = 0;
+
+        // Sectors per track (default)
+        fs->currentsector.sector[24] = 0x3F;
+        fs->currentsector.sector[25] = 0x00;
+
+        // Heads (default)
+        fs->currentsector.sector[26] = 0xFF;
+        fs->currentsector.sector[27] = 0x00;
+
+        // Hidden sectors
+        fs->currentsector.sector[28] = 0x00;
+        fs->currentsector.sector[29] = 0x00;
+        fs->currentsector.sector[30] = 0x00;
+        fs->currentsector.sector[31] = 0x00;
+
+        // Total sectors for this volume
+        fs->currentsector.sector[32] = (uint8)((vol_sectors>>0)&0xFF);
+        fs->currentsector.sector[33] = (uint8)((vol_sectors>>8)&0xFF);
+        fs->currentsector.sector[34] = (uint8)((vol_sectors>>16)&0xFF);
+        fs->currentsector.sector[35] = (uint8)((vol_sectors>>24)&0xFF);
+
+        total_clusters = (vol_sectors / fs->sectors_per_cluster) + 1;
+        fs->fat_sectors = (total_clusters/(FAT_SECTOR_SIZE/4)) + 1;
+
+        // BPB_FATSz32
+        fs->currentsector.sector[36] = (uint8)((fs->fat_sectors>>0)&0xFF);
+        fs->currentsector.sector[37] = (uint8)((fs->fat_sectors>>8)&0xFF);
+        fs->currentsector.sector[38] = (uint8)((fs->fat_sectors>>16)&0xFF);
+        fs->currentsector.sector[39] = (uint8)((fs->fat_sectors>>24)&0xFF);
+
+        // BPB_ExtFlags
+        fs->currentsector.sector[40] = 0;
+        fs->currentsector.sector[41] = 0;
+
+        // BPB_FSVer
+        fs->currentsector.sector[42] = 0;
+        fs->currentsector.sector[43] = 0;
+
+        // BPB_RootClus
+        fs->currentsector.sector[44] = (uint8)((fs->rootdir_first_cluster>>0)&0xFF);
+        fs->currentsector.sector[45] = (uint8)((fs->rootdir_first_cluster>>8)&0xFF);
+        fs->currentsector.sector[46] = (uint8)((fs->rootdir_first_cluster>>16)&0xFF);
+        fs->currentsector.sector[47] = (uint8)((fs->rootdir_first_cluster>>24)&0xFF);
+
+        // BPB_FSInfo
+        fs->currentsector.sector[48] = (uint8)((fs->fs_info_sector>>0)&0xFF);
+        fs->currentsector.sector[49] = (uint8)((fs->fs_info_sector>>8)&0xFF);
+
+        // BPB_BkBootSec
+        fs->currentsector.sector[50] = 6;
+        fs->currentsector.sector[51] = 0;
+
+        // Drive number
+        fs->currentsector.sector[64] = 0x00;
+
+        // Boot signature
+        fs->currentsector.sector[66] = 0x29;
+
+        // Volume ID
+        fs->currentsector.sector[67] = 0x12;
+        fs->currentsector.sector[68] = 0x34;
+        fs->currentsector.sector[69] = 0x56;
+        fs->currentsector.sector[70] = 0x78;
+
+        // Volume name
+        for (i=0;i<11;i++)
+        {
+            if (i < (int)strlen(name))
+                fs->currentsector.sector[i+71] = name[i];
+            else
+                fs->currentsector.sector[i+71] = ' ';
+        }
+
+        // File sys type
+        fs->currentsector.sector[82] = 'F';
+        fs->currentsector.sector[83] = 'A';
+        fs->currentsector.sector[84] = 'T';
+        fs->currentsector.sector[85] = '3';
+        fs->currentsector.sector[86] = '2';
+        fs->currentsector.sector[87] = ' ';
+        fs->currentsector.sector[88] = ' ';
+        fs->currentsector.sector[89] = ' ';
+
+        // Signature
+        fs->currentsector.sector[510] = 0x55;
+        fs->currentsector.sector[511] = 0xAA;
+    }
+
+    if (fs->disk_io.write_media(boot_sector_lba, fs->currentsector.sector, 1))
+        return 1;
+    else
+        return 0;
+}
+//-----------------------------------------------------------------------------
+// fatfs_create_fsinfo_sector: Create the FSInfo sector (FAT32)
+//-----------------------------------------------------------------------------
+static int fatfs_create_fsinfo_sector(struct fatfs *fs, uint32 sector_lba)
+{
+    // Zero sector initially
+    memset(fs->currentsector.sector, 0, FAT_SECTOR_SIZE);
+
+    // FSI_LeadSig
+    fs->currentsector.sector[0] = 0x52;
+    fs->currentsector.sector[1] = 0x52;
+    fs->currentsector.sector[2] = 0x61;
+    fs->currentsector.sector[3] = 0x41;
+
+    // FSI_StrucSig
+    fs->currentsector.sector[484] = 0x72;
+    fs->currentsector.sector[485] = 0x72;
+    fs->currentsector.sector[486] = 0x41;
+    fs->currentsector.sector[487] = 0x61;
+
+    // FSI_Free_Count
+    fs->currentsector.sector[488] = 0xFF;
+    fs->currentsector.sector[489] = 0xFF;
+    fs->currentsector.sector[490] = 0xFF;
+    fs->currentsector.sector[491] = 0xFF;
+
+    // FSI_Nxt_Free
+    fs->currentsector.sector[492] = 0xFF;
+    fs->currentsector.sector[493] = 0xFF;
+    fs->currentsector.sector[494] = 0xFF;
+    fs->currentsector.sector[495] = 0xFF;
+
+    // Signature
+    fs->currentsector.sector[510] = 0x55;
+    fs->currentsector.sector[511] = 0xAA;
+
+    if (fs->disk_io.write_media(sector_lba, fs->currentsector.sector, 1))
+        return 1;
+    else
+        return 0;
+}
+//-----------------------------------------------------------------------------
+// fatfs_erase_fat: Erase FAT table using fs details in fs struct
+//-----------------------------------------------------------------------------
+static int fatfs_erase_fat(struct fatfs *fs, int is_fat32)
+{
+    uint32 i;
+
+    // Zero sector initially
+    memset(fs->currentsector.sector, 0, FAT_SECTOR_SIZE);
+
+    // Initialise default allocate / reserved clusters
+    if (!is_fat32)
+    {
+        SET_16BIT_WORD(fs->currentsector.sector, 0, 0xFFF8);
+        SET_16BIT_WORD(fs->currentsector.sector, 2, 0xFFFF);
+    }
+    else
+    {
+        SET_32BIT_WORD(fs->currentsector.sector, 0, 0x0FFFFFF8);
+        SET_32BIT_WORD(fs->currentsector.sector, 4, 0xFFFFFFFF);
+        SET_32BIT_WORD(fs->currentsector.sector, 8, 0x0FFFFFFF);
+    }
+
+    if (!fs->disk_io.write_media(fs->fat_begin_lba + 0, fs->currentsector.sector, 1))
+        return 0;
+
+    // Zero remaining FAT sectors
+    memset(fs->currentsector.sector, 0, FAT_SECTOR_SIZE);
+    for (i=1;ifat_sectors*fs->num_of_fats;i++)
+        if (!fs->disk_io.write_media(fs->fat_begin_lba + i, fs->currentsector.sector, 1))
+            return 0;
+
+    return 1;
+}
+//-----------------------------------------------------------------------------
+// fatfs_format_fat16: Format a FAT16 partition
+//-----------------------------------------------------------------------------
+int fatfs_format_fat16(struct fatfs *fs, uint32 volume_sectors, const char *name)
+{
+    fs->currentsector.address = FAT32_INVALID_CLUSTER;
+    fs->currentsector.dirty = 0;
+
+    fs->next_free_cluster = 0; // Invalid
+
+    fatfs_fat_init(fs);
+
+    // Make sure we have read + write functions
+    if (!fs->disk_io.read_media || !fs->disk_io.write_media)
+        return FAT_INIT_MEDIA_ACCESS_ERROR;
+
+    // Volume is FAT16
+    fs->fat_type = FAT_TYPE_16;
+
+    // Not valid for FAT16
+    fs->fs_info_sector = 0;
+    fs->rootdir_first_cluster = 0;
+
+    // Sector 0: Boot sector
+    // NOTE: We don't need an MBR, it is a waste of a good sector!
+    fs->lba_begin = 0;
+    if (!fatfs_create_boot_sector(fs, fs->lba_begin, volume_sectors, name, 0))
+        return 0;
+
+    // For FAT16 (which this may be), rootdir_first_cluster is actuall rootdir_first_sector
+    fs->rootdir_first_sector = fs->reserved_sectors + (fs->num_of_fats * fs->fat_sectors);
+    fs->rootdir_sectors = ((fs->root_entry_count * 32) + (FAT_SECTOR_SIZE - 1)) / FAT_SECTOR_SIZE;
+
+    // First FAT LBA address
+    fs->fat_begin_lba = fs->lba_begin + fs->reserved_sectors;
+
+    // The address of the first data cluster on this volume
+    fs->cluster_begin_lba = fs->fat_begin_lba + (fs->num_of_fats * fs->fat_sectors);
+
+    // Initialise FAT sectors
+    if (!fatfs_erase_fat(fs, 0))
+        return 0;
+
+    // Erase Root directory
+    if (!fatfs_erase_sectors(fs, fs->lba_begin + fs->rootdir_first_sector, fs->rootdir_sectors))
+        return 0;
+
+    return 1;
+}
+//-----------------------------------------------------------------------------
+// fatfs_format_fat32: Format a FAT32 partition
+//-----------------------------------------------------------------------------
+int fatfs_format_fat32(struct fatfs *fs, uint32 volume_sectors, const char *name)
+{
+    fs->currentsector.address = FAT32_INVALID_CLUSTER;
+    fs->currentsector.dirty = 0;
+
+    fs->next_free_cluster = 0; // Invalid
+
+    fatfs_fat_init(fs);
+
+    // Make sure we have read + write functions
+    if (!fs->disk_io.read_media || !fs->disk_io.write_media)
+        return FAT_INIT_MEDIA_ACCESS_ERROR;
+
+    // Volume is FAT32
+    fs->fat_type = FAT_TYPE_32;
+
+    // Basic defaults for normal FAT32 partitions
+    fs->fs_info_sector = 1;
+    fs->rootdir_first_cluster = 2;
+
+    // Sector 0: Boot sector
+    // NOTE: We don't need an MBR, it is a waste of a good sector!
+    fs->lba_begin = 0;
+    if (!fatfs_create_boot_sector(fs, fs->lba_begin, volume_sectors, name, 1))
+        return 0;
+
+    // First FAT LBA address
+    fs->fat_begin_lba = fs->lba_begin + fs->reserved_sectors;
+
+    // The address of the first data cluster on this volume
+    fs->cluster_begin_lba = fs->fat_begin_lba + (fs->num_of_fats * fs->fat_sectors);
+
+    // Initialise FSInfo sector
+    if (!fatfs_create_fsinfo_sector(fs, fs->fs_info_sector))
+        return 0;
+
+    // Initialise FAT sectors
+    if (!fatfs_erase_fat(fs, 1))
+        return 0;
+
+    // Erase Root directory
+    if (!fatfs_erase_sectors(fs, fatfs_lba_of_cluster(fs, fs->rootdir_first_cluster), fs->sectors_per_cluster))
+        return 0;
+
+    return 1;
+}
+//-----------------------------------------------------------------------------
+// fatfs_format: Format a partition with either FAT16 or FAT32 based on size
+//-----------------------------------------------------------------------------
+int fatfs_format(struct fatfs *fs, uint32 volume_sectors, const char *name)
+{
+    // 2GB - 32K limit for safe behaviour for FAT16
+    if (volume_sectors <= 4194304)
+        return fatfs_format_fat16(fs, volume_sectors, name);
+    else
+        return fatfs_format_fat32(fs, volume_sectors, name);
+}
+#endif /*FATFS_INC_FORMAT_SUPPORT*/
diff --git a/sys/fs/fat/fat_format.h b/sys/fs/fat/fat_format.h
new file mode 100644
index 0000000..a8a6bba
--- /dev/null
+++ b/sys/fs/fat/fat_format.h
@@ -0,0 +1,15 @@
+#ifndef __FAT_FORMAT_H__
+#define __FAT_FORMAT_H__
+
+#include "fat_defs.h"
+#include "fat_opts.h"
+#include "fat_access.h"
+
+//-----------------------------------------------------------------------------
+// Prototypes
+//-----------------------------------------------------------------------------
+int fatfs_format(struct fatfs *fs, uint32 volume_sectors, const char *name);
+int fatfs_format_fat16(struct fatfs *fs, uint32 volume_sectors, const char *name);
+int fatfs_format_fat32(struct fatfs *fs, uint32 volume_sectors, const char *name);
+
+#endif
diff --git a/sys/fs/fat/fat_list.h b/sys/fs/fat/fat_list.h
new file mode 100644
index 0000000..bd386ef
--- /dev/null
+++ b/sys/fs/fat/fat_list.h
@@ -0,0 +1,161 @@
+#ifndef __FAT_LIST_H__
+#define __FAT_LIST_H__
+
+#ifndef FAT_ASSERT
+    #define FAT_ASSERT(x)
+#endif
+
+#ifndef FAT_INLINE
+    #define FAT_INLINE
+#endif
+
+//-----------------------------------------------------------------
+// Types
+//-----------------------------------------------------------------
+struct fat_list;
+
+struct fat_node
+{
+    struct fat_node    *previous;
+    struct fat_node    *next;
+};
+
+struct fat_list
+{
+    struct fat_node    *head;
+    struct fat_node    *tail;
+};
+
+//-----------------------------------------------------------------
+// Macros
+//-----------------------------------------------------------------
+#define fat_list_entry(p, t, m)     p ? ((t *)((char *)(p)-(char*)(&((t *)0)->m))) : 0
+#define fat_list_next(l, p)         (p)->next
+#define fat_list_prev(l, p)         (p)->previous
+#define fat_list_first(l)           (l)->head
+#define fat_list_last(l)            (l)->tail
+#define fat_list_for_each(l, p)     for ((p) = (l)->head; (p); (p) = (p)->next)
+
+//-----------------------------------------------------------------
+// Inline Functions
+//-----------------------------------------------------------------
+
+//-----------------------------------------------------------------
+// fat_list_init:
+//-----------------------------------------------------------------
+static FAT_INLINE void fat_list_init(struct fat_list *list)
+{
+    FAT_ASSERT(list);
+
+    list->head = list->tail = 0;
+}
+//-----------------------------------------------------------------
+// fat_list_remove:
+//-----------------------------------------------------------------
+static FAT_INLINE void fat_list_remove(struct fat_list *list, struct fat_node *node)
+{
+    FAT_ASSERT(list);
+    FAT_ASSERT(node);
+
+    if(!node->previous)
+        list->head = node->next;
+    else
+        node->previous->next = node->next;
+
+    if(!node->next)
+        list->tail = node->previous;
+    else
+        node->next->previous = node->previous;
+}
+//-----------------------------------------------------------------
+// fat_list_insert_after:
+//-----------------------------------------------------------------
+static FAT_INLINE void fat_list_insert_after(struct fat_list *list, struct fat_node *node, struct fat_node *new_node)
+{
+    FAT_ASSERT(list);
+    FAT_ASSERT(node);
+    FAT_ASSERT(new_node);
+
+    new_node->previous = node;
+    new_node->next = node->next;
+    if (!node->next)
+        list->tail = new_node;
+    else
+        node->next->previous = new_node;
+    node->next = new_node;
+}
+//-----------------------------------------------------------------
+// fat_list_insert_before:
+//-----------------------------------------------------------------
+static FAT_INLINE void fat_list_insert_before(struct fat_list *list, struct fat_node *node, struct fat_node *new_node)
+{
+    FAT_ASSERT(list);
+    FAT_ASSERT(node);
+    FAT_ASSERT(new_node);
+
+    new_node->previous = node->previous;
+    new_node->next = node;
+    if (!node->previous)
+        list->head = new_node;
+    else
+        node->previous->next = new_node;
+    node->previous = new_node;
+}
+//-----------------------------------------------------------------
+// fat_list_insert_first:
+//-----------------------------------------------------------------
+static FAT_INLINE void fat_list_insert_first(struct fat_list *list, struct fat_node *node)
+{
+    FAT_ASSERT(list);
+    FAT_ASSERT(node);
+
+    if (!list->head)
+    {
+        list->head = node;
+        list->tail = node;
+        node->previous = 0;
+        node->next = 0;
+    }
+    else
+        fat_list_insert_before(list, list->head, node);
+}
+//-----------------------------------------------------------------
+// fat_list_insert_last:
+//-----------------------------------------------------------------
+static FAT_INLINE void fat_list_insert_last(struct fat_list *list, struct fat_node *node)
+{
+    FAT_ASSERT(list);
+    FAT_ASSERT(node);
+
+    if (!list->tail)
+        fat_list_insert_first(list, node);
+     else
+        fat_list_insert_after(list, list->tail, node);
+}
+//-----------------------------------------------------------------
+// fat_list_is_empty:
+//-----------------------------------------------------------------
+static FAT_INLINE int fat_list_is_empty(struct fat_list *list)
+{
+    FAT_ASSERT(list);
+
+    return !list->head;
+}
+//-----------------------------------------------------------------
+// fat_list_pop_head:
+//-----------------------------------------------------------------
+static FAT_INLINE struct fat_node * fat_list_pop_head(struct fat_list *list)
+{
+    struct fat_node * node;
+
+    FAT_ASSERT(list);
+
+    node = fat_list_first(list);
+    if (node)
+        fat_list_remove(list, node);
+
+    return node;
+}
+
+#endif
+
diff --git a/sys/fs/fat/fat_misc.c b/sys/fs/fat/fat_misc.c
new file mode 100644
index 0000000..cbf6f08
--- /dev/null
+++ b/sys/fs/fat/fat_misc.c
@@ -0,0 +1,505 @@
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//                            FAT16/32 File IO Library
+//                                    V2.6
+//                              Ultra-Embedded.com
+//                            Copyright 2003 - 2012
+//
+//                         Email: admin@ultra-embedded.com
+//
+//                                License: GPL
+//   If you would like a version with a more permissive license for use in
+//   closed source commercial applications please contact me for details.
+//-----------------------------------------------------------------------------
+//
+// This file is part of FAT File IO Library.
+//
+// FAT File IO Library is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// FAT File IO Library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FAT File IO Library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+#include 
+#include 
+#include "fat_misc.h"
+
+//-----------------------------------------------------------------------------
+// fatfs_lfn_cache_init: Clear long file name cache
+//-----------------------------------------------------------------------------
+void fatfs_lfn_cache_init(struct lfn_cache *lfn, int wipeTable)
+{
+    int i = 0;
+
+    lfn->no_of_strings = 0;
+
+#if FATFS_INC_LFN_SUPPORT
+
+    // Zero out buffer also
+    if (wipeTable)
+        for (i=0;iString[i], 0x00, MAX_LFN_ENTRY_LENGTH);
+#endif
+}
+//-----------------------------------------------------------------------------
+// fatfs_lfn_cache_entry - Function extracts long file name text from sector
+// at a specific offset
+//-----------------------------------------------------------------------------
+#if FATFS_INC_LFN_SUPPORT
+void fatfs_lfn_cache_entry(struct lfn_cache *lfn, uint8 *entryBuffer)
+{
+    uint8 LFNIndex, i;
+    LFNIndex = entryBuffer[0] & 0x1F;
+
+    // Limit file name to cache size!
+    if (LFNIndex > MAX_LONGFILENAME_ENTRIES)
+        return ;
+
+    // This is an error condition
+    if (LFNIndex == 0)
+        return ;
+
+    if (lfn->no_of_strings == 0)
+        lfn->no_of_strings = LFNIndex;
+
+    lfn->String[LFNIndex-1][0] = entryBuffer[1];
+    lfn->String[LFNIndex-1][1] = entryBuffer[3];
+    lfn->String[LFNIndex-1][2] = entryBuffer[5];
+    lfn->String[LFNIndex-1][3] = entryBuffer[7];
+    lfn->String[LFNIndex-1][4] = entryBuffer[9];
+    lfn->String[LFNIndex-1][5] = entryBuffer[0x0E];
+    lfn->String[LFNIndex-1][6] = entryBuffer[0x10];
+    lfn->String[LFNIndex-1][7] = entryBuffer[0x12];
+    lfn->String[LFNIndex-1][8] = entryBuffer[0x14];
+    lfn->String[LFNIndex-1][9] = entryBuffer[0x16];
+    lfn->String[LFNIndex-1][10] = entryBuffer[0x18];
+    lfn->String[LFNIndex-1][11] = entryBuffer[0x1C];
+    lfn->String[LFNIndex-1][12] = entryBuffer[0x1E];
+
+    for (i=0; iString[LFNIndex-1][i]==0xFF)
+            lfn->String[LFNIndex-1][i] = 0x20; // Replace with spaces
+}
+#endif
+//-----------------------------------------------------------------------------
+// fatfs_lfn_cache_get: Get a reference to the long filename
+//-----------------------------------------------------------------------------
+#if FATFS_INC_LFN_SUPPORT
+char* fatfs_lfn_cache_get(struct lfn_cache *lfn)
+{
+    // Null terminate long filename
+    if (lfn->no_of_strings == MAX_LONGFILENAME_ENTRIES)
+        lfn->Null = '\0';
+    else if (lfn->no_of_strings)
+        lfn->String[lfn->no_of_strings][0] = '\0';
+    else
+        lfn->String[0][0] = '\0';
+
+    return (char*)&lfn->String[0][0];
+}
+#endif
+//-----------------------------------------------------------------------------
+// fatfs_entry_lfn_text: If LFN text entry found
+//-----------------------------------------------------------------------------
+#if FATFS_INC_LFN_SUPPORT
+int fatfs_entry_lfn_text(struct fat_dir_entry *entry)
+{
+    if ((entry->Attr & FILE_ATTR_LFN_TEXT) == FILE_ATTR_LFN_TEXT)
+        return 1;
+    else
+        return 0;
+}
+#endif
+//-----------------------------------------------------------------------------
+// fatfs_entry_lfn_invalid: If SFN found not relating to LFN
+//-----------------------------------------------------------------------------
+#if FATFS_INC_LFN_SUPPORT
+int fatfs_entry_lfn_invalid(struct fat_dir_entry *entry)
+{
+    if ( (entry->Name[0]==FILE_HEADER_BLANK)  ||
+         (entry->Name[0]==FILE_HEADER_DELETED)||
+         (entry->Attr==FILE_ATTR_VOLUME_ID) ||
+         (entry->Attr & FILE_ATTR_SYSHID) )
+        return 1;
+    else
+        return 0;
+}
+#endif
+//-----------------------------------------------------------------------------
+// fatfs_entry_lfn_exists: If LFN exists and correlation SFN found
+//-----------------------------------------------------------------------------
+#if FATFS_INC_LFN_SUPPORT
+int fatfs_entry_lfn_exists(struct lfn_cache *lfn, struct fat_dir_entry *entry)
+{
+    if ( (entry->Attr!=FILE_ATTR_LFN_TEXT) &&
+         (entry->Name[0]!=FILE_HEADER_BLANK) &&
+         (entry->Name[0]!=FILE_HEADER_DELETED) &&
+         (entry->Attr!=FILE_ATTR_VOLUME_ID) &&
+         (!(entry->Attr&FILE_ATTR_SYSHID)) &&
+         (lfn->no_of_strings) )
+        return 1;
+    else
+        return 0;
+}
+#endif
+//-----------------------------------------------------------------------------
+// fatfs_entry_sfn_only: If SFN only exists
+//-----------------------------------------------------------------------------
+int fatfs_entry_sfn_only(struct fat_dir_entry *entry)
+{
+    if ( (entry->Attr!=FILE_ATTR_LFN_TEXT) &&
+         (entry->Name[0]!=FILE_HEADER_BLANK) &&
+         (entry->Name[0]!=FILE_HEADER_DELETED) &&
+         (entry->Attr!=FILE_ATTR_VOLUME_ID) &&
+         (!(entry->Attr&FILE_ATTR_SYSHID)) )
+        return 1;
+    else
+        return 0;
+}
+// TODO: FILE_ATTR_SYSHID ?!?!??!
+//-----------------------------------------------------------------------------
+// fatfs_entry_is_dir: Returns 1 if a directory
+//-----------------------------------------------------------------------------
+int fatfs_entry_is_dir(struct fat_dir_entry *entry)
+{
+    if (entry->Attr & FILE_TYPE_DIR)
+        return 1;
+    else
+        return 0;
+}
+//-----------------------------------------------------------------------------
+// fatfs_entry_is_file: Returns 1 is a file entry
+//-----------------------------------------------------------------------------
+int fatfs_entry_is_file(struct fat_dir_entry *entry)
+{
+    if (entry->Attr & FILE_TYPE_FILE)
+        return 1;
+    else
+        return 0;
+}
+//-----------------------------------------------------------------------------
+// fatfs_lfn_entries_required: Calculate number of 13 characters entries
+//-----------------------------------------------------------------------------
+#if FATFS_INC_LFN_SUPPORT
+int fatfs_lfn_entries_required(char *filename)
+{
+    int length = (int)strlen(filename);
+
+    if (length)
+        return (length + MAX_LFN_ENTRY_LENGTH - 1) / MAX_LFN_ENTRY_LENGTH;
+    else
+        return 0;
+}
+#endif
+//-----------------------------------------------------------------------------
+// fatfs_filename_to_lfn:
+//-----------------------------------------------------------------------------
+#if FATFS_INC_LFN_SUPPORT
+void fatfs_filename_to_lfn(char *filename, uint8 *buffer, int entry, uint8 sfnChk)
+{
+    int i;
+    int nameIndexes[MAX_LFN_ENTRY_LENGTH] = {1,3,5,7,9,0x0E,0x10,0x12,0x14,0x16,0x18,0x1C,0x1E};
+
+    // 13 characters entries
+    int length = (int)strlen(filename);
+    int entriesRequired = fatfs_lfn_entries_required(filename);
+
+    // Filename offset
+    int start = entry * MAX_LFN_ENTRY_LENGTH;
+
+    // Initialise to zeros
+    memset(buffer, 0x00, FAT_DIR_ENTRY_SIZE);
+
+    // LFN entry number
+    buffer[0] = (uint8)(((entriesRequired-1)==entry)?(0x40|(entry+1)):(entry+1));
+
+    // LFN flag
+    buffer[11] = 0x0F;
+
+    // Checksum of short filename
+    buffer[13] = sfnChk;
+
+    // Copy to buffer
+    for (i=0;iName[i] = shortfilename[i];
+
+    // Unless we have a RTC we might as well set these to 1980
+    entry->CrtTimeTenth = 0x00;
+    entry->CrtTime[1] = entry->CrtTime[0] = 0x00;
+    entry->CrtDate[1] = 0x00;
+    entry->CrtDate[0] = 0x20;
+    entry->LstAccDate[1] = 0x00;
+    entry->LstAccDate[0] = 0x20;
+    entry->WrtTime[1] = entry->WrtTime[0] = 0x00;
+    entry->WrtDate[1] = 0x00;
+    entry->WrtDate[0] = 0x20;
+
+    if (!dir)
+        entry->Attr = FILE_TYPE_FILE;
+    else
+        entry->Attr = FILE_TYPE_DIR;
+
+    entry->NTRes = 0x00;
+
+    entry->FstClusHI = FAT_HTONS((uint16)((startCluster>>16) & 0xFFFF));
+    entry->FstClusLO = FAT_HTONS((uint16)((startCluster>>0) & 0xFFFF));
+    entry->FileSize = FAT_HTONL(size);
+}
+#endif
+//-----------------------------------------------------------------------------
+// fatfs_lfn_create_sfn: Create a padded SFN
+//-----------------------------------------------------------------------------
+#if FATFS_INC_WRITE_SUPPORT
+int fatfs_lfn_create_sfn(char *sfn_output, char *filename)
+{
+    int i;
+    int dotPos = -1;
+    char ext[3];
+    int pos;
+    int len = (int)strlen(filename);
+
+    // Invalid to start with .
+    if (filename[0]=='.')
+        return 0;
+
+    memset(sfn_output, ' ', FAT_SFN_SIZE_FULL);
+    memset(ext, ' ', 3);
+
+    // Find dot seperator
+    for (i = 0; i< len; i++)
+    {
+        if (filename[i]=='.')
+            dotPos = i;
+    }
+
+    // Extract extensions
+    if (dotPos!=-1)
+    {
+        // Copy first three chars of extension
+        for (i = (dotPos+1); i < (dotPos+1+3); i++)
+            if (i= 'a' && filename[i] <= 'z')
+                sfn_output[pos++] = filename[i] - 'a' + 'A';
+            else
+                sfn_output[pos++] = filename[i];
+        }
+
+        // Fill upto 8 characters
+        if (pos==FAT_SFN_SIZE_PARTIAL)
+            break;
+    }
+
+    // Add extension part
+    for (i=FAT_SFN_SIZE_PARTIAL;i= 'a' && ext[i-FAT_SFN_SIZE_PARTIAL] <= 'z')
+            sfn_output[i] = ext[i-FAT_SFN_SIZE_PARTIAL] - 'a' + 'A';
+        else
+            sfn_output[i] = ext[i-FAT_SFN_SIZE_PARTIAL];
+    }
+
+    return 1;
+}
+//-----------------------------------------------------------------------------
+// fatfs_itoa:
+//-----------------------------------------------------------------------------
+static void fatfs_itoa(uint32 num, char *s)
+{
+    char* cp;
+    char outbuf[12];
+    const char digits[] = "0123456789ABCDEF";
+
+    // Build string backwards
+    cp = outbuf;
+    do
+    {
+        *cp++ = digits[(int)(num % 10)];
+    }
+    while ((num /= 10) > 0);
+
+    *cp-- = 0;
+
+    // Copy in forwards
+    while (cp >= outbuf)
+        *s++ = *cp--;
+
+    *s = 0;
+}
+#endif
+//-----------------------------------------------------------------------------
+// fatfs_lfn_generate_tail:
+// sfn_input = Input short filename, spaced format & in upper case
+// sfn_output = Output short filename with tail
+//-----------------------------------------------------------------------------
+#if FATFS_INC_LFN_SUPPORT
+#if FATFS_INC_WRITE_SUPPORT
+int fatfs_lfn_generate_tail(char *sfn_output, char *sfn_input, uint32 tailNum)
+{
+    int tail_chars;
+    char tail_str[12];
+
+    if (tailNum > 99999)
+        return 0;
+
+    // Convert to number
+    memset(tail_str, 0x00, sizeof(tail_str));
+    tail_str[0] = '~';
+    fatfs_itoa(tailNum, tail_str+1);
+
+    // Copy in base filename
+    memcpy(sfn_output, sfn_input, FAT_SFN_SIZE_FULL);
+
+    // Overwrite with tail
+    tail_chars = (int)strlen(tail_str);
+    memcpy(sfn_output+(FAT_SFN_SIZE_PARTIAL-tail_chars), tail_str, tail_chars);
+
+    return 1;
+}
+#endif
+#endif
+//-----------------------------------------------------------------------------
+// fatfs_convert_from_fat_time: Convert FAT time to h/m/s
+//-----------------------------------------------------------------------------
+#if FATFS_INC_TIME_DATE_SUPPORT
+void fatfs_convert_from_fat_time(uint16 fat_time, int *hours, int *minutes, int *seconds)
+{
+    *hours = (fat_time >> FAT_TIME_HOURS_SHIFT) & FAT_TIME_HOURS_MASK;
+    *minutes = (fat_time >> FAT_TIME_MINUTES_SHIFT) & FAT_TIME_MINUTES_MASK;
+    *seconds = (fat_time >> FAT_TIME_SECONDS_SHIFT) & FAT_TIME_SECONDS_MASK;
+    *seconds = *seconds * FAT_TIME_SECONDS_SCALE;
+}
+//-----------------------------------------------------------------------------
+// fatfs_convert_from_fat_date: Convert FAT date to d/m/y
+//-----------------------------------------------------------------------------
+void fatfs_convert_from_fat_date(uint16 fat_date, int *day, int *month, int *year)
+{
+    *day = (fat_date >> FAT_DATE_DAY_SHIFT) & FAT_DATE_DAY_MASK;
+    *month = (fat_date >> FAT_DATE_MONTH_SHIFT) & FAT_DATE_MONTH_MASK;
+    *year = (fat_date >> FAT_DATE_YEAR_SHIFT) & FAT_DATE_YEAR_MASK;
+    *year = *year + FAT_DATE_YEAR_OFFSET;
+}
+//-----------------------------------------------------------------------------
+// fatfs_convert_to_fat_time: Convert h/m/s to FAT time
+//-----------------------------------------------------------------------------
+uint16 fatfs_convert_to_fat_time(int hours, int minutes, int seconds)
+{
+    uint16 fat_time = 0;
+
+    // Most FAT times are to a resolution of 2 seconds
+    seconds /= FAT_TIME_SECONDS_SCALE;
+
+    fat_time = (hours & FAT_TIME_HOURS_MASK) << FAT_TIME_HOURS_SHIFT;
+    fat_time|= (minutes & FAT_TIME_MINUTES_MASK) << FAT_TIME_MINUTES_SHIFT;
+    fat_time|= (seconds & FAT_TIME_SECONDS_MASK) << FAT_TIME_SECONDS_SHIFT;
+
+    return fat_time;
+}
+//-----------------------------------------------------------------------------
+// fatfs_convert_to_fat_date: Convert d/m/y to FAT date
+//-----------------------------------------------------------------------------
+uint16 fatfs_convert_to_fat_date(int day, int month, int year)
+{
+    uint16 fat_date = 0;
+
+    // FAT dates are relative to 1980
+    if (year >= FAT_DATE_YEAR_OFFSET)
+        year -= FAT_DATE_YEAR_OFFSET;
+
+    fat_date = (day & FAT_DATE_DAY_MASK) << FAT_DATE_DAY_SHIFT;
+    fat_date|= (month & FAT_DATE_MONTH_MASK) << FAT_DATE_MONTH_SHIFT;
+    fat_date|= (year & FAT_DATE_YEAR_MASK) << FAT_DATE_YEAR_SHIFT;
+
+    return fat_date;
+}
+#endif
+//-----------------------------------------------------------------------------
+// fatfs_print_sector:
+//-----------------------------------------------------------------------------
+#ifdef FATFS_DEBUG
+void fatfs_print_sector(uint32 sector, uint8 *data)
+{
+    int i;
+    int j;
+
+    FAT_PRINTF(("Sector %d:\n", sector));
+
+    for (i=0;i 31 && ch < 127)
+                {
+                    FAT_PRINTF(("%c", ch));
+                }
+                else
+                {
+                    FAT_PRINTF(("."));
+                }
+            }
+
+            FAT_PRINTF(("\n"));
+        }
+    }
+}
+#endif
diff --git a/sys/fs/fat/fat_misc.h b/sys/fs/fat/fat_misc.h
new file mode 100644
index 0000000..0c02634
--- /dev/null
+++ b/sys/fs/fat/fat_misc.h
@@ -0,0 +1,63 @@
+#ifndef __FAT_MISC_H__
+#define __FAT_MISC_H__
+
+#include "fat_defs.h"
+#include "fat_opts.h"
+
+//-----------------------------------------------------------------------------
+// Defines
+//-----------------------------------------------------------------------------
+#define MAX_LONGFILENAME_ENTRIES    20
+#define MAX_LFN_ENTRY_LENGTH        13
+
+//-----------------------------------------------------------------------------
+// Macros
+//-----------------------------------------------------------------------------
+#define GET_32BIT_WORD(buffer, location)    ( ((uint32)buffer[location+3]<<24) + ((uint32)buffer[location+2]<<16) + ((uint32)buffer[location+1]<<8) + (uint32)buffer[location+0] )
+#define GET_16BIT_WORD(buffer, location)    ( ((uint16)buffer[location+1]<<8) + (uint16)buffer[location+0] )
+
+#define SET_32BIT_WORD(buffer, location, value)    { buffer[location+0] = (uint8)((value)&0xFF); \
+                                                  buffer[location+1] = (uint8)((value>>8)&0xFF); \
+                                                  buffer[location+2] = (uint8)((value>>16)&0xFF); \
+                                                  buffer[location+3] = (uint8)((value>>24)&0xFF); }
+
+#define SET_16BIT_WORD(buffer, location, value)    { buffer[location+0] = (uint8)((value)&0xFF); \
+                                                  buffer[location+1] = (uint8)((value>>8)&0xFF); }
+
+//-----------------------------------------------------------------------------
+// Structures
+//-----------------------------------------------------------------------------
+struct lfn_cache
+{
+#if FATFS_INC_LFN_SUPPORT
+    // Long File Name Structure (max 260 LFN length)
+    uint8 String[MAX_LONGFILENAME_ENTRIES][MAX_LFN_ENTRY_LENGTH];
+    uint8 Null;
+#endif
+    uint8 no_of_strings;
+};
+
+//-----------------------------------------------------------------------------
+// Prototypes
+//-----------------------------------------------------------------------------
+void    fatfs_lfn_cache_init(struct lfn_cache *lfn, int wipeTable);
+void    fatfs_lfn_cache_entry(struct lfn_cache *lfn, uint8 *entryBuffer);
+char*   fatfs_lfn_cache_get(struct lfn_cache *lfn);
+int     fatfs_entry_lfn_text(struct fat_dir_entry *entry);
+int     fatfs_entry_lfn_invalid(struct fat_dir_entry *entry);
+int     fatfs_entry_lfn_exists(struct lfn_cache *lfn, struct fat_dir_entry *entry);
+int     fatfs_entry_sfn_only(struct fat_dir_entry *entry);
+int     fatfs_entry_is_dir(struct fat_dir_entry *entry);
+int     fatfs_entry_is_file(struct fat_dir_entry *entry);
+int     fatfs_lfn_entries_required(char *filename);
+void    fatfs_filename_to_lfn(char *filename, uint8 *buffer, int entry, uint8 sfnChk);
+void    fatfs_sfn_create_entry(char *shortfilename, uint32 size, uint32 startCluster, struct fat_dir_entry *entry, int dir);
+int     fatfs_lfn_create_sfn(char *sfn_output, char *filename);
+int     fatfs_lfn_generate_tail(char *sfn_output, char *sfn_input, uint32 tailNum);
+void    fatfs_convert_from_fat_time(uint16 fat_time, int *hours, int *minutes, int *seconds);
+void    fatfs_convert_from_fat_date(uint16 fat_date, int *day, int *month, int *year);
+uint16  fatfs_convert_to_fat_time(int hours, int minutes, int seconds);
+uint16  fatfs_convert_to_fat_date(int day, int month, int year);
+void    fatfs_print_sector(uint32 sector, uint8 *data);
+
+#endif
diff --git a/sys/fs/fat/fat_opts.h b/sys/fs/fat/fat_opts.h
new file mode 100644
index 0000000..ac4dc86
--- /dev/null
+++ b/sys/fs/fat/fat_opts.h
@@ -0,0 +1,90 @@
+#ifndef __FAT_OPTS_H__
+#define __FAT_OPTS_H__
+
+#ifdef FATFS_USE_CUSTOM_OPTS_FILE
+    #include "fat_custom.h"
+#endif
+
+//-------------------------------------------------------------
+// Configuration
+//-------------------------------------------------------------
+
+// Is the processor little endian (1) or big endian (0)
+#ifndef FATFS_IS_LITTLE_ENDIAN
+    #define FATFS_IS_LITTLE_ENDIAN          1
+#endif
+
+// Max filename Length
+#ifndef FATFS_MAX_LONG_FILENAME
+    #define FATFS_MAX_LONG_FILENAME         260
+#endif
+
+// Max open files (reduce to lower memory requirements)
+#ifndef FATFS_MAX_OPEN_FILES
+    #define FATFS_MAX_OPEN_FILES            2
+#endif
+
+// Number of sectors per FAT_BUFFER (min 1)
+#ifndef FAT_BUFFER_SECTORS
+    #define FAT_BUFFER_SECTORS              1
+#endif
+
+// Max FAT sectors to buffer (min 1)
+// (mem used is FAT_BUFFERS * FAT_BUFFER_SECTORS * FAT_SECTOR_SIZE)
+#ifndef FAT_BUFFERS
+    #define FAT_BUFFERS                     1
+#endif
+
+// Size of cluster chain cache (can be undefined)
+// Mem used = FAT_CLUSTER_CACHE_ENTRIES * 4 * 2
+// Improves access speed considerably
+//#define FAT_CLUSTER_CACHE_ENTRIES         128
+
+// Include support for writing files (1 / 0)?
+#ifndef FATFS_INC_WRITE_SUPPORT
+    #define FATFS_INC_WRITE_SUPPORT         1
+#endif
+
+// Support long filenames (1 / 0)?
+// (if not (0) only 8.3 format is supported)
+#ifndef FATFS_INC_LFN_SUPPORT
+    #define FATFS_INC_LFN_SUPPORT           1
+#endif
+
+// Support directory listing (1 / 0)?
+#ifndef FATFS_DIR_LIST_SUPPORT
+    #define FATFS_DIR_LIST_SUPPORT          1
+#endif
+
+// Support time/date (1 / 0)?
+#ifndef FATFS_INC_TIME_DATE_SUPPORT
+    #define FATFS_INC_TIME_DATE_SUPPORT     0
+#endif
+
+// Include support for formatting disks (1 / 0)?
+#ifndef FATFS_INC_FORMAT_SUPPORT
+    #define FATFS_INC_FORMAT_SUPPORT        1
+#endif
+
+// Sector size used
+#define FAT_SECTOR_SIZE                     512
+
+// Printf output (directory listing / debug)
+#ifndef FAT_PRINTF
+    // Don't include stdio, but there is a printf function available
+    #ifdef FAT_PRINTF_NOINC_STDIO
+        extern int printf(const char* ctrl1, ... );
+        #define FAT_PRINTF(a)               printf a
+    // Include stdio to use printf
+    #else
+        #include 
+        #define FAT_PRINTF(a)               printf a
+    #endif
+#endif
+
+// Time/Date support requires time.h
+#if FATFS_INC_TIME_DATE_SUPPORT
+    #include 
+#endif
+
+#endif
diff --git a/sys/fs/fat/fat_string.c b/sys/fs/fat/fat_string.c
new file mode 100644
index 0000000..f7206ce
--- /dev/null
+++ b/sys/fs/fat/fat_string.c
@@ -0,0 +1,514 @@
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//                            FAT16/32 File IO Library
+//                                    V2.6
+//                              Ultra-Embedded.com
+//                            Copyright 2003 - 2012
+//
+//                         Email: admin@ultra-embedded.com
+//
+//                                License: GPL
+//   If you would like a version with a more permissive license for use in
+//   closed source commercial applications please contact me for details.
+//-----------------------------------------------------------------------------
+//
+// This file is part of FAT File IO Library.
+//
+// FAT File IO Library is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// FAT File IO Library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FAT File IO Library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+#include 
+#include 
+#include "fat_string.h"
+
+//-----------------------------------------------------------------------------
+// fatfs_total_path_levels: Take a filename and path and count the sub levels
+// of folders. E.g. C:\folder\file.zip = 1 level
+// Acceptable input formats are:
+//        c:\folder\file.zip
+//        /dev/etc/samba.conf
+// Returns: -1 = Error, 0 or more = Ok
+//-----------------------------------------------------------------------------
+int fatfs_total_path_levels(char *path)
+{
+    int levels = 0;
+    char expectedchar;
+
+    if (!path)
+        return -1;
+
+    // Acceptable formats:
+    //  c:\folder\file.zip
+    //  /dev/etc/samba.conf
+    if (*path == '/')
+    {
+        expectedchar = '/';
+        path++;
+    }
+    else if (path[1] == ':' || path[2] == '\\')
+    {
+        expectedchar = '\\';
+        path += 3;
+    }
+    else
+        return -1;
+
+    // Count levels in path string
+    while (*path)
+    {
+        // Fast forward through actual subdir text to next slash
+        for (; *path; )
+        {
+            // If slash detected escape from for loop
+            if (*path == expectedchar) { path++; break; }
+            path++;
+        }
+
+        // Increase number of subdirs founds
+        levels++;
+    }
+
+    // Subtract the file itself
+    return levels-1;
+}
+//-----------------------------------------------------------------------------
+// fatfs_get_substring: Get a substring from 'path' which contains the folder
+// (or file) at the specified level.
+// E.g. C:\folder\file.zip : Level 0 = C:\folder, Level 1 = file.zip
+// Returns: -1 = Error, 0 = Ok
+//-----------------------------------------------------------------------------
+int fatfs_get_substring(char *path, int levelreq, char *output, int max_len)
+{
+    int i;
+    int pathlen=0;
+    int levels=0;
+    int copypnt=0;
+    char expectedchar;
+
+    if (!path || max_len <= 0)
+        return -1;
+
+    // Acceptable formats:
+    //  c:\folder\file.zip
+    //  /dev/etc/samba.conf
+    if (*path == '/')
+    {
+        expectedchar = '/';
+        path++;
+    }
+    else if (path[1] == ':' || path[2] == '\\')
+    {
+        expectedchar = '\\';
+        path += 3;
+    }
+    else
+        return -1;
+
+    // Get string length of path
+    pathlen = (int)strlen (path);
+
+    // Loop through the number of times as characters in 'path'
+    for (i = 0; i path = C:\folder  filename = file.zip
+// E.g. C:\file.zip -> path = [blank]  filename = file.zip
+//-----------------------------------------------------------------------------
+int fatfs_split_path(char *full_path, char *path, int max_path, char *filename, int max_filename)
+{
+    int strindex;
+
+    // Count the levels to the filepath
+    int levels = fatfs_total_path_levels(full_path);
+    if (levels == -1)
+        return -1;
+
+    // Get filename part of string
+    if (fatfs_get_substring(full_path, levels, filename, max_filename) != 0)
+        return -1;
+
+    // If root file
+    if (levels == 0)
+        path[0] = '\0';
+    else
+    {
+        strindex = (int)strlen(full_path) - (int)strlen(filename);
+        if (strindex > max_path)
+            strindex = max_path;
+
+        memcpy(path, full_path, strindex);
+        path[strindex-1] = '\0';
+    }
+
+    return 0;
+}
+//-----------------------------------------------------------------------------
+// FileString_StrCmpNoCase: Compare two strings case with case sensitivity
+//-----------------------------------------------------------------------------
+static int FileString_StrCmpNoCase(char *s1, char *s2, int n)
+{
+    int diff;
+    char a,b;
+
+    while (n--)
+    {
+        a = *s1;
+        b = *s2;
+
+        // Make lower case if uppercase
+        if ((a>='A') && (a<='Z'))
+            a+= 32;
+        if ((b>='A') && (b<='Z'))
+            b+= 32;
+
+        diff = a - b;
+
+        // If different
+        if (diff)
+            return diff;
+
+        // If run out of strings
+        if ( (*s1 == 0) || (*s2 == 0) )
+            break;
+
+        s1++;
+        s2++;
+    }
+    return 0;
+}
+//-----------------------------------------------------------------------------
+// FileString_GetExtension: Get index to extension within filename
+// Returns -1 if not found or index otherwise
+//-----------------------------------------------------------------------------
+static int FileString_GetExtension(char *str)
+{
+    int dotPos = -1;
+    char *strSrc = str;
+
+    // Find last '.' in string (if at all)
+    while (*strSrc)
+    {
+        if (*strSrc=='.')
+            dotPos = (int)(strSrc-str);
+
+        strSrc++;
+    }
+
+    return dotPos;
+}
+//-----------------------------------------------------------------------------
+// FileString_TrimLength: Get length of string excluding trailing spaces
+// Returns -1 if not found or index otherwise
+//-----------------------------------------------------------------------------
+static int FileString_TrimLength(char *str, int strLen)
+{
+    int length = strLen;
+    char *strSrc = str+strLen-1;
+
+    // Find last non white space
+    while (strLen != 0)
+    {
+        if (*strSrc == ' ')
+            length = (int)(strSrc - str);
+        else
+            break;
+
+        strSrc--;
+        strLen--;
+    }
+
+    return length;
+}
+//-----------------------------------------------------------------------------
+// fatfs_compare_names: Compare two filenames (without copying or changing origonals)
+// Returns 1 if match, 0 if not
+//-----------------------------------------------------------------------------
+int fatfs_compare_names(char* strA, char* strB)
+{
+    char *ext1 = NULL;
+    char *ext2 = NULL;
+    int ext1Pos, ext2Pos;
+    int file1Len, file2Len;
+
+    // Get both files extension
+    ext1Pos = FileString_GetExtension(strA);
+    ext2Pos = FileString_GetExtension(strB);
+
+    // NOTE: Extension position can be different for matching
+    // filename if trailing space are present before it!
+    // Check that if one has an extension, so does the other
+    if ((ext1Pos==-1) && (ext2Pos!=-1))
+        return 0;
+    if ((ext2Pos==-1) && (ext1Pos!=-1))
+        return 0;
+
+    // If they both have extensions, compare them
+    if (ext1Pos!=-1)
+    {
+        // Set pointer to start of extension
+        ext1 = strA+ext1Pos+1;
+        ext2 = strB+ext2Pos+1;
+
+        // Verify that the file extension lengths match!
+        if (strlen(ext1) != strlen(ext2))
+            return 0;
+
+        // If they dont match
+        if (FileString_StrCmpNoCase(ext1, ext2, (int)strlen(ext1))!=0)
+            return 0;
+
+        // Filelength is upto extensions
+        file1Len = ext1Pos;
+        file2Len = ext2Pos;
+    }
+    // No extensions
+    else
+    {
+        // Filelength is actual filelength
+        file1Len = (int)strlen(strA);
+        file2Len = (int)strlen(strB);
+    }
+
+    // Find length without trailing spaces (before ext)
+    file1Len = FileString_TrimLength(strA, file1Len);
+    file2Len = FileString_TrimLength(strB, file2Len);
+
+    // Check the file lengths match
+    if (file1Len!=file2Len)
+        return 0;
+
+    // Compare main part of filenames
+    if (FileString_StrCmpNoCase(strA, strB, file1Len)!=0)
+        return 0;
+    else
+        return 1;
+}
+//-----------------------------------------------------------------------------
+// fatfs_string_ends_with_slash: Does the string end with a slash (\ or /)
+//-----------------------------------------------------------------------------
+int fatfs_string_ends_with_slash(char *path)
+{
+    if (path)
+    {
+        while (*path)
+        {
+            // Last character?
+            if (!(*(path+1)))
+            {
+                if (*path == '\\' || *path == '/')
+                    return 1;
+            }
+
+            path++;
+        }
+    }
+
+    return 0;
+}
+//-----------------------------------------------------------------------------
+// fatfs_get_sfn_display_name: Get display name for SFN entry
+//-----------------------------------------------------------------------------
+int fatfs_get_sfn_display_name(char* out, char* in)
+{
+    int len = 0;
+    while (*in && len <= 11)
+    {
+        char a = *in++;
+
+        if (a == ' ')
+            continue;
+        // Make lower case if uppercase
+        else if ((a>='A') && (a<='Z'))
+            a+= 32;
+
+        *out++ = a;
+        len++;
+    }
+
+    *out = '\0';
+    return 1;
+}
+//-----------------------------------------------------------------------------
+// fatfs_get_extension: Get extension of filename passed in 'filename'.
+// Returned extension is always lower case.
+// Returns: 1 if ok, 0 if not.
+//-----------------------------------------------------------------------------
+int fatfs_get_extension(char* filename, char* out, int maxlen)
+{
+    int len = 0;
+
+    // Get files extension offset
+    int ext_pos = FileString_GetExtension(filename);
+
+    if (ext_pos > 0 && out && maxlen)
+    {
+        filename += ext_pos + 1;
+
+        while (*filename && len < (maxlen-1))
+        {
+            char a = *filename++;
+
+            // Make lowercase if uppercase
+            if ((a>='A') && (a<='Z'))
+                a+= 32;
+
+            *out++ = a;
+            len++;
+        }
+
+        *out = '\0';
+        return 1;
+    }
+
+    return 0;
+}
+//-----------------------------------------------------------------------------
+// fatfs_create_path_string: Append path & filename to create file path string.
+// Returns: 1 if ok, 0 if not.
+//-----------------------------------------------------------------------------
+int fatfs_create_path_string(char* path, char *filename, char* out, int maxlen)
+{
+    int len = 0;
+    char last = 0;
+    char seperator = '/';
+
+    if (path && filename && out && maxlen > 0)
+    {
+        while (*path && len < (maxlen-2))
+        {
+            last = *path++;
+            if (last == '\\')
+                seperator = '\\';
+            *out++ = last;
+            len++;
+        }
+
+        // Add a seperator if trailing one not found
+        if (last != '\\' && last != '/')
+            *out++ = seperator;
+
+        while (*filename && len < (maxlen-1))
+        {
+            *out++ = *filename++;
+            len++;
+        }
+
+        *out = '\0';
+
+        return 1;
+    }
+
+    return 0;
+}
+//-----------------------------------------------------------------------------
+// Test Bench
+//-----------------------------------------------------------------------------
+#ifdef FAT_STRING_TESTBENCH
+void main(void)
+{
+    char output[255];
+    char output2[255];
+
+    assert(fatfs_total_path_levels("C:\\folder\\file.zip") == 1);
+    assert(fatfs_total_path_levels("C:\\file.zip") == 0);
+    assert(fatfs_total_path_levels("C:\\folder\\folder2\\file.zip") == 2);
+    assert(fatfs_total_path_levels("C:\\") == -1);
+    assert(fatfs_total_path_levels("") == -1);
+    assert(fatfs_total_path_levels("/dev/etc/file.zip") == 2);
+    assert(fatfs_total_path_levels("/dev/file.zip") == 1);
+
+    assert(fatfs_get_substring("C:\\folder\\file.zip", 0, output, sizeof(output)) == 0);
+    assert(strcmp(output, "folder") == 0);
+
+    assert(fatfs_get_substring("C:\\folder\\file.zip", 1, output, sizeof(output)) == 0);
+    assert(strcmp(output, "file.zip") == 0);
+
+    assert(fatfs_get_substring("/dev/etc/file.zip", 0, output, sizeof(output)) == 0);
+    assert(strcmp(output, "dev") == 0);
+
+    assert(fatfs_get_substring("/dev/etc/file.zip", 1, output, sizeof(output)) == 0);
+    assert(strcmp(output, "etc") == 0);
+
+    assert(fatfs_get_substring("/dev/etc/file.zip", 2, output, sizeof(output)) == 0);
+    assert(strcmp(output, "file.zip") == 0);
+
+    assert(fatfs_split_path("C:\\folder\\file.zip", output, sizeof(output), output2, sizeof(output2)) == 0);
+    assert(strcmp(output, "C:\\folder") == 0);
+    assert(strcmp(output2, "file.zip") == 0);
+
+    assert(fatfs_split_path("C:\\file.zip", output, sizeof(output), output2, sizeof(output2)) == 0);
+    assert(output[0] == 0);
+    assert(strcmp(output2, "file.zip") == 0);
+
+    assert(fatfs_split_path("/dev/etc/file.zip", output, sizeof(output), output2, sizeof(output2)) == 0);
+    assert(strcmp(output, "/dev/etc") == 0);
+    assert(strcmp(output2, "file.zip") == 0);
+
+    assert(FileString_GetExtension("C:\\file.zip") == strlen("C:\\file"));
+    assert(FileString_GetExtension("C:\\file.zip.ext") == strlen("C:\\file.zip"));
+    assert(FileString_GetExtension("C:\\file.zip.") == strlen("C:\\file.zip"));
+
+    assert(FileString_TrimLength("C:\\file.zip", strlen("C:\\file.zip")) == strlen("C:\\file.zip"));
+    assert(FileString_TrimLength("C:\\file.zip   ", strlen("C:\\file.zip   ")) == strlen("C:\\file.zip"));
+    assert(FileString_TrimLength("   ", strlen("   ")) == 0);
+
+    assert(fatfs_compare_names("C:\\file.ext", "C:\\file.ext") == 1);
+    assert(fatfs_compare_names("C:\\file2.ext", "C:\\file.ext") == 0);
+    assert(fatfs_compare_names("C:\\file  .ext", "C:\\file.ext") == 1);
+    assert(fatfs_compare_names("C:\\file  .ext", "C:\\file2.ext") == 0);
+
+    assert(fatfs_string_ends_with_slash("C:\\folder") == 0);
+    assert(fatfs_string_ends_with_slash("C:\\folder\\") == 1);
+    assert(fatfs_string_ends_with_slash("/path") == 0);
+    assert(fatfs_string_ends_with_slash("/path/a") == 0);
+    assert(fatfs_string_ends_with_slash("/path/") == 1);
+
+    assert(fatfs_get_extension("/mypath/file.wav", output, 4) == 1);
+    assert(strcmp(output, "wav") == 0);
+    assert(fatfs_get_extension("/mypath/file.WAV", output, 4) == 1);
+    assert(strcmp(output, "wav") == 0);
+    assert(fatfs_get_extension("/mypath/file.zip", output, 4) == 1);
+    assert(strcmp(output, "ext") != 0);
+
+    assert(fatfs_create_path_string("/mydir1", "myfile.txt", output, sizeof(output)) == 1);
+    assert(strcmp(output, "/mydir1/myfile.txt") == 0);
+    assert(fatfs_create_path_string("/mydir2/", "myfile2.txt", output, sizeof(output)) == 1);
+    assert(strcmp(output, "/mydir2/myfile2.txt") == 0);
+    assert(fatfs_create_path_string("C:\\mydir3", "myfile3.txt", output, sizeof(output)) == 1);
+    assert(strcmp(output, "C:\\mydir3\\myfile3.txt") == 0);
+}
+#endif
diff --git a/sys/fs/fat/fat_string.h b/sys/fs/fat/fat_string.h
new file mode 100644
index 0000000..90ca8e0
--- /dev/null
+++ b/sys/fs/fat/fat_string.h
@@ -0,0 +1,20 @@
+#ifndef __FILESTRING_H__
+#define __FILESTRING_H__
+
+//-----------------------------------------------------------------------------
+// Prototypes
+//-----------------------------------------------------------------------------
+int fatfs_total_path_levels(char *path);
+int fatfs_get_substring(char *Path, int levelreq, char *output, int max_len);
+int fatfs_split_path(char *FullPath, char *Path, int max_path, char *FileName, int max_filename);
+int fatfs_compare_names(char* strA, char* strB);
+int fatfs_string_ends_with_slash(char *path);
+int fatfs_get_sfn_display_name(char* out, char* in);
+int fatfs_get_extension(char* filename, char* out, int maxlen);
+int fatfs_create_path_string(char* path, char *filename, char* out, int maxlen);
+
+#ifndef NULL
+    #define NULL 0
+#endif
+
+#endif
diff --git a/sys/fs/fat/fat_table.c b/sys/fs/fat/fat_table.c
new file mode 100644
index 0000000..8d05d3b
--- /dev/null
+++ b/sys/fs/fat/fat_table.c
@@ -0,0 +1,478 @@
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//                            FAT16/32 File IO Library
+//                                    V2.6
+//                              Ultra-Embedded.com
+//                            Copyright 2003 - 2012
+//
+//                         Email: admin@ultra-embedded.com
+//
+//                                License: GPL
+//   If you would like a version with a more permissive license for use in
+//   closed source commercial applications please contact me for details.
+//-----------------------------------------------------------------------------
+//
+// This file is part of FAT File IO Library.
+//
+// FAT File IO Library is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// FAT File IO Library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FAT File IO Library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+#include 
+#include "fat_defs.h"
+#include "fat_access.h"
+#include "fat_table.h"
+
+#ifndef FAT_BUFFERS
+    #define FAT_BUFFERS 1
+#endif
+
+#ifndef FAT_BUFFER_SECTORS
+    #define FAT_BUFFER_SECTORS 1
+#endif
+
+#if FAT_BUFFERS < 1 || FAT_BUFFER_SECTORS < 1
+    #error "FAT_BUFFERS & FAT_BUFFER_SECTORS must be at least 1"
+#endif
+
+//-----------------------------------------------------------------------------
+//                            FAT Sector Buffer
+//-----------------------------------------------------------------------------
+#define FAT32_GET_32BIT_WORD(pbuf, location)        ( GET_32BIT_WORD(pbuf->ptr, location) )
+#define FAT32_SET_32BIT_WORD(pbuf, location, value) { SET_32BIT_WORD(pbuf->ptr, location, value); pbuf->dirty = 1; }
+#define FAT16_GET_16BIT_WORD(pbuf, location)        ( GET_16BIT_WORD(pbuf->ptr, location) )
+#define FAT16_SET_16BIT_WORD(pbuf, location, value) { SET_16BIT_WORD(pbuf->ptr, location, value); pbuf->dirty = 1; }
+
+//-----------------------------------------------------------------------------
+// fatfs_fat_init:
+//-----------------------------------------------------------------------------
+void fatfs_fat_init(struct fatfs *fs)
+{
+    int i;
+
+    // FAT buffer chain head
+    fs->fat_buffer_head = NULL;
+
+    for (i=0;ifat_buffers[i].address = FAT32_INVALID_CLUSTER;
+        fs->fat_buffers[i].dirty = 0;
+        memset(fs->fat_buffers[i].sector, 0x00, sizeof(fs->fat_buffers[i].sector));
+        fs->fat_buffers[i].ptr = NULL;
+
+        // Add to head of queue
+        fs->fat_buffers[i].next = fs->fat_buffer_head;
+        fs->fat_buffer_head = &fs->fat_buffers[i];
+    }
+}
+//-----------------------------------------------------------------------------
+// fatfs_fat_writeback: Writeback 'dirty' FAT sectors to disk
+//-----------------------------------------------------------------------------
+static int fatfs_fat_writeback(struct fatfs *fs, struct fat_buffer *pcur)
+{
+    if (pcur)
+    {
+        // Writeback sector if changed
+        if (pcur->dirty)
+        {
+            if (fs->disk_io.write_media)
+            {
+                uint32 sectors = FAT_BUFFER_SECTORS;
+                uint32 offset = pcur->address - fs->fat_begin_lba;
+
+                // Limit to sectors used for the FAT
+                if ((offset + FAT_BUFFER_SECTORS) <= fs->fat_sectors)
+                    sectors = FAT_BUFFER_SECTORS;
+                else
+                    sectors = fs->fat_sectors - offset;
+
+                if (!fs->disk_io.write_media(pcur->address, pcur->sector, sectors))
+                    return 0;
+            }
+
+            pcur->dirty = 0;
+        }
+
+        return 1;
+    }
+    else
+        return 0;
+}
+//-----------------------------------------------------------------------------
+// fatfs_fat_read_sector: Read a FAT sector
+//-----------------------------------------------------------------------------
+static struct fat_buffer *fatfs_fat_read_sector(struct fatfs *fs, uint32 sector)
+{
+    struct fat_buffer *last = NULL;
+    struct fat_buffer *pcur = fs->fat_buffer_head;
+
+    // Itterate through sector buffer list
+    while (pcur)
+    {
+        // Sector within this buffer?
+        if ((sector >= pcur->address) && (sector < (pcur->address + FAT_BUFFER_SECTORS)))
+            break;
+
+        // End of list?
+        if (pcur->next == NULL)
+        {
+            // Remove buffer from list
+            if (last)
+                last->next = NULL;
+            // We the first and last buffer in the chain?
+            else
+                fs->fat_buffer_head = NULL;
+        }
+
+        last = pcur;
+        pcur = pcur->next;
+    }
+
+    // We found the sector already in FAT buffer chain
+    if (pcur)
+    {
+        pcur->ptr = (uint8 *)(pcur->sector + ((sector - pcur->address) * FAT_SECTOR_SIZE));
+        return pcur;
+    }
+
+    // Else, we removed the last item from the list
+    pcur = last;
+
+    // Add to start of sector buffer list (now newest sector)
+    pcur->next = fs->fat_buffer_head;
+    fs->fat_buffer_head = pcur;
+
+    // Writeback sector if changed
+    if (pcur->dirty)
+        if (!fatfs_fat_writeback(fs, pcur))
+            return 0;
+
+    // Address is now new sector
+    pcur->address = sector;
+
+    // Read next sector
+    if (!fs->disk_io.read_media(pcur->address, pcur->sector, FAT_BUFFER_SECTORS))
+    {
+        // Read failed, invalidate buffer address
+        pcur->address = FAT32_INVALID_CLUSTER;
+        return NULL;
+    }
+
+    pcur->ptr = pcur->sector;
+    return pcur;
+}
+//-----------------------------------------------------------------------------
+// fatfs_fat_purge: Purge 'dirty' FAT sectors to disk
+//-----------------------------------------------------------------------------
+int fatfs_fat_purge(struct fatfs *fs)
+{
+    struct fat_buffer *pcur = fs->fat_buffer_head;
+
+    // Itterate through sector buffer list
+    while (pcur)
+    {
+        // Writeback sector if changed
+        if (pcur->dirty)
+            if (!fatfs_fat_writeback(fs, pcur))
+                return 0;
+
+        pcur = pcur->next;
+    }
+
+    return 1;
+}
+
+//-----------------------------------------------------------------------------
+//                        General FAT Table Operations
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// fatfs_find_next_cluster: Return cluster number of next cluster in chain by
+// reading FAT table and traversing it. Return 0xffffffff for end of chain.
+//-----------------------------------------------------------------------------
+uint32 fatfs_find_next_cluster(struct fatfs *fs, uint32 current_cluster)
+{
+    uint32 fat_sector_offset, position;
+    uint32 nextcluster;
+    struct fat_buffer *pbuf;
+
+    // Why is '..' labelled with cluster 0 when it should be 2 ??
+    if (current_cluster == 0)
+        current_cluster = 2;
+
+    // Find which sector of FAT table to read
+    if (fs->fat_type == FAT_TYPE_16)
+        fat_sector_offset = current_cluster / 256;
+    else
+        fat_sector_offset = current_cluster / 128;
+
+    // Read FAT sector into buffer
+    pbuf = fatfs_fat_read_sector(fs, fs->fat_begin_lba+fat_sector_offset);
+    if (!pbuf)
+        return (FAT32_LAST_CLUSTER);
+
+    if (fs->fat_type == FAT_TYPE_16)
+    {
+        // Find 32 bit entry of current sector relating to cluster number
+        position = (current_cluster - (fat_sector_offset * 256)) * 2;
+
+        // Read Next Clusters value from Sector Buffer
+        nextcluster = FAT16_GET_16BIT_WORD(pbuf, (uint16)position);
+
+        // If end of chain found
+        if (nextcluster >= 0xFFF8 && nextcluster <= 0xFFFF)
+            return (FAT32_LAST_CLUSTER);
+    }
+    else
+    {
+        // Find 32 bit entry of current sector relating to cluster number
+        position = (current_cluster - (fat_sector_offset * 128)) * 4;
+
+        // Read Next Clusters value from Sector Buffer
+        nextcluster = FAT32_GET_32BIT_WORD(pbuf, (uint16)position);
+
+        // Mask out MS 4 bits (its 28bit addressing)
+        nextcluster = nextcluster & 0x0FFFFFFF;
+
+        // If end of chain found
+        if (nextcluster >= 0x0FFFFFF8 && nextcluster <= 0x0FFFFFFF)
+            return (FAT32_LAST_CLUSTER);
+    }
+
+    // Else return next cluster
+    return (nextcluster);
+}
+//-----------------------------------------------------------------------------
+// fatfs_set_fs_info_next_free_cluster: Write the next free cluster to the FSINFO table
+//-----------------------------------------------------------------------------
+void fatfs_set_fs_info_next_free_cluster(struct fatfs *fs, uint32 newValue)
+{
+    if (fs->fat_type == FAT_TYPE_16)
+        ;
+    else
+    {
+        // Load sector to change it
+        struct fat_buffer *pbuf = fatfs_fat_read_sector(fs, fs->lba_begin+fs->fs_info_sector);
+        if (!pbuf)
+            return ;
+
+        // Change
+        FAT32_SET_32BIT_WORD(pbuf, 492, newValue);
+        fs->next_free_cluster = newValue;
+
+        // Write back FSINFO sector to disk
+        if (fs->disk_io.write_media)
+            fs->disk_io.write_media(pbuf->address, pbuf->sector, 1);
+
+        // Invalidate cache entry
+        pbuf->address = FAT32_INVALID_CLUSTER;
+        pbuf->dirty = 0;
+    }
+}
+//-----------------------------------------------------------------------------
+// fatfs_find_blank_cluster: Find a free cluster entry by reading the FAT
+//-----------------------------------------------------------------------------
+#if FATFS_INC_WRITE_SUPPORT
+int fatfs_find_blank_cluster(struct fatfs *fs, uint32 start_cluster, uint32 *free_cluster)
+{
+    uint32 fat_sector_offset, position;
+    uint32 nextcluster;
+    uint32 current_cluster = start_cluster;
+    struct fat_buffer *pbuf;
+
+    do
+    {
+        // Find which sector of FAT table to read
+        if (fs->fat_type == FAT_TYPE_16)
+            fat_sector_offset = current_cluster / 256;
+        else
+            fat_sector_offset = current_cluster / 128;
+
+        if ( fat_sector_offset < fs->fat_sectors)
+        {
+            // Read FAT sector into buffer
+            pbuf = fatfs_fat_read_sector(fs, fs->fat_begin_lba+fat_sector_offset);
+            if (!pbuf)
+                return 0;
+
+            if (fs->fat_type == FAT_TYPE_16)
+            {
+                // Find 32 bit entry of current sector relating to cluster number
+                position = (current_cluster - (fat_sector_offset * 256)) * 2;
+
+                // Read Next Clusters value from Sector Buffer
+                nextcluster = FAT16_GET_16BIT_WORD(pbuf, (uint16)position);
+            }
+            else
+            {
+                // Find 32 bit entry of current sector relating to cluster number
+                position = (current_cluster - (fat_sector_offset * 128)) * 4;
+
+                // Read Next Clusters value from Sector Buffer
+                nextcluster = FAT32_GET_32BIT_WORD(pbuf, (uint16)position);
+
+                // Mask out MS 4 bits (its 28bit addressing)
+                nextcluster = nextcluster & 0x0FFFFFFF;
+            }
+
+            if (nextcluster !=0 )
+                current_cluster++;
+        }
+        else
+            // Otherwise, run out of FAT sectors to check...
+            return 0;
+    }
+    while (nextcluster != 0x0);
+
+    // Found blank entry
+    *free_cluster = current_cluster;
+    return 1;
+}
+#endif
+//-----------------------------------------------------------------------------
+// fatfs_fat_set_cluster: Set a cluster link in the chain. NOTE: Immediate
+// write (slow).
+//-----------------------------------------------------------------------------
+#if FATFS_INC_WRITE_SUPPORT
+int fatfs_fat_set_cluster(struct fatfs *fs, uint32 cluster, uint32 next_cluster)
+{
+    struct fat_buffer *pbuf;
+    uint32 fat_sector_offset, position;
+
+    // Find which sector of FAT table to read
+    if (fs->fat_type == FAT_TYPE_16)
+        fat_sector_offset = cluster / 256;
+    else
+        fat_sector_offset = cluster / 128;
+
+    // Read FAT sector into buffer
+    pbuf = fatfs_fat_read_sector(fs, fs->fat_begin_lba+fat_sector_offset);
+    if (!pbuf)
+        return 0;
+
+    if (fs->fat_type == FAT_TYPE_16)
+    {
+        // Find 16 bit entry of current sector relating to cluster number
+        position = (cluster - (fat_sector_offset * 256)) * 2;
+
+        // Write Next Clusters value to Sector Buffer
+        FAT16_SET_16BIT_WORD(pbuf, (uint16)position, ((uint16)next_cluster));
+    }
+    else
+    {
+        // Find 32 bit entry of current sector relating to cluster number
+        position = (cluster - (fat_sector_offset * 128)) * 4;
+
+        // Write Next Clusters value to Sector Buffer
+        FAT32_SET_32BIT_WORD(pbuf, (uint16)position, next_cluster);
+    }
+
+    return 1;
+}
+#endif
+//-----------------------------------------------------------------------------
+// fatfs_free_cluster_chain: Follow a chain marking each element as free
+//-----------------------------------------------------------------------------
+#if FATFS_INC_WRITE_SUPPORT
+int fatfs_free_cluster_chain(struct fatfs *fs, uint32 start_cluster)
+{
+    uint32 last_cluster;
+    uint32 next_cluster = start_cluster;
+
+    // Loop until end of chain
+    while ( (next_cluster != FAT32_LAST_CLUSTER) && (next_cluster != 0x00000000) )
+    {
+        last_cluster = next_cluster;
+
+        // Find next link
+        next_cluster = fatfs_find_next_cluster(fs, next_cluster);
+
+        // Clear last link
+        fatfs_fat_set_cluster(fs, last_cluster, 0x00000000);
+    }
+
+    return 1;
+}
+#endif
+//-----------------------------------------------------------------------------
+// fatfs_fat_add_cluster_to_chain: Follow a chain marking and then add a new entry
+// to the current tail.
+//-----------------------------------------------------------------------------
+#if FATFS_INC_WRITE_SUPPORT
+int fatfs_fat_add_cluster_to_chain(struct fatfs *fs, uint32 start_cluster, uint32 newEntry)
+{
+    uint32 last_cluster = FAT32_LAST_CLUSTER;
+    uint32 next_cluster = start_cluster;
+
+    if (start_cluster == FAT32_LAST_CLUSTER)
+        return 0;
+
+    // Loop until end of chain
+    while ( next_cluster != FAT32_LAST_CLUSTER )
+    {
+        last_cluster = next_cluster;
+
+        // Find next link
+        next_cluster = fatfs_find_next_cluster(fs, next_cluster);
+        if (!next_cluster)
+            return 0;
+    }
+
+    // Add link in for new cluster
+    fatfs_fat_set_cluster(fs, last_cluster, newEntry);
+
+    // Mark new cluster as end of chain
+    fatfs_fat_set_cluster(fs, newEntry, FAT32_LAST_CLUSTER);
+
+    return 1;
+}
+#endif
+//-----------------------------------------------------------------------------
+// fatfs_count_free_clusters:
+//-----------------------------------------------------------------------------
+uint32 fatfs_count_free_clusters(struct fatfs *fs)
+{
+    uint32 i,j;
+    uint32 count = 0;
+    struct fat_buffer *pbuf;
+
+    for (i = 0; i < fs->fat_sectors; i++)
+    {
+        // Read FAT sector into buffer
+        pbuf = fatfs_fat_read_sector(fs, fs->fat_begin_lba + i);
+        if (!pbuf)
+            break;
+
+        for (j = 0; j < FAT_SECTOR_SIZE; )
+        {
+            if (fs->fat_type == FAT_TYPE_16)
+            {
+                if (FAT16_GET_16BIT_WORD(pbuf, (uint16)j) == 0)
+                    count++;
+
+                j += 2;
+            }
+            else
+            {
+                if (FAT32_GET_32BIT_WORD(pbuf, (uint16)j) == 0)
+                    count++;
+
+                j += 4;
+            }
+        }
+    }
+
+    return count;
+}
diff --git a/sys/fs/fat/fat_table.h b/sys/fs/fat/fat_table.h
new file mode 100644
index 0000000..ead75f3
--- /dev/null
+++ b/sys/fs/fat/fat_table.h
@@ -0,0 +1,20 @@
+#ifndef __FAT_TABLE_H__
+#define __FAT_TABLE_H__
+
+#include "fat_opts.h"
+#include "fat_misc.h"
+
+//-----------------------------------------------------------------------------
+// Prototypes
+//-----------------------------------------------------------------------------
+void    fatfs_fat_init(struct fatfs *fs);
+int     fatfs_fat_purge(struct fatfs *fs);
+uint32  fatfs_find_next_cluster(struct fatfs *fs, uint32 current_cluster);
+void    fatfs_set_fs_info_next_free_cluster(struct fatfs *fs, uint32 newValue);
+int     fatfs_find_blank_cluster(struct fatfs *fs, uint32 start_cluster, uint32 *free_cluster);
+int     fatfs_fat_set_cluster(struct fatfs *fs, uint32 cluster, uint32 next_cluster);
+int     fatfs_fat_add_cluster_to_chain(struct fatfs *fs, uint32 start_cluster, uint32 newEntry);
+int     fatfs_free_cluster_chain(struct fatfs *fs, uint32 start_cluster);
+uint32  fatfs_count_free_clusters(struct fatfs *fs);
+
+#endif
diff --git a/sys/fs/fat/fat_types.h b/sys/fs/fat/fat_types.h
new file mode 100644
index 0000000..5e2cca8
--- /dev/null
+++ b/sys/fs/fat/fat_types.h
@@ -0,0 +1,69 @@
+#ifndef __FAT_TYPES_H__
+#define __FAT_TYPES_H__
+
+// Detect 64-bit compilation on GCC
+#if defined(__GNUC__) && defined(__SIZEOF_LONG__)
+    #if __SIZEOF_LONG__ == 8
+        #define FATFS_DEF_UINT32_AS_INT
+    #endif
+#endif
+
+//-------------------------------------------------------------
+// System specific types
+//-------------------------------------------------------------
+#ifndef FATFS_NO_DEF_TYPES
+    typedef unsigned char uint8;
+    typedef unsigned short uint16;
+
+    // If compiling on a 64-bit machine, use int as 32-bits
+    #ifdef FATFS_DEF_UINT32_AS_INT
+        typedef unsigned int uint32;
+    // Else for 32-bit machines & embedded systems, use long...
+    #else
+        typedef unsigned long uint32;
+    #endif
+#endif
+
+#ifndef NULL
+    #define NULL 0
+#endif
+
+//-------------------------------------------------------------
+// Endian Macros
+//-------------------------------------------------------------
+// FAT is little endian so big endian systems need to swap words
+
+// Little Endian - No swap required
+#if FATFS_IS_LITTLE_ENDIAN == 1
+
+    #define FAT_HTONS(n) (n)
+    #define FAT_HTONL(n) (n)
+
+// Big Endian - Swap required
+#else
+
+    #define FAT_HTONS(n) ((((uint16)((n) & 0xff)) << 8) | (((n) & 0xff00) >> 8))
+    #define FAT_HTONL(n) (((((uint32)(n) & 0xFF)) << 24) | \
+                    ((((uint32)(n) & 0xFF00)) << 8) | \
+                    ((((uint32)(n) & 0xFF0000)) >> 8) | \
+                    ((((uint32)(n) & 0xFF000000)) >> 24))
+
+#endif
+
+//-------------------------------------------------------------
+// Structure Packing Compile Options
+//-------------------------------------------------------------
+#ifdef __GNUC__
+    #define STRUCT_PACK
+    #define STRUCT_PACK_BEGIN
+    #define STRUCT_PACK_END
+    #define STRUCT_PACKED           __attribute__ ((packed))
+#else
+    // Other compilers may require other methods of packing structures
+    #define STRUCT_PACK
+    #define STRUCT_PACK_BEGIN
+    #define STRUCT_PACK_END
+    #define STRUCT_PACKED
+#endif
+
+#endif
diff --git a/sys/fs/fat/fat_write.c b/sys/fs/fat/fat_write.c
new file mode 100644
index 0000000..0718cb1
--- /dev/null
+++ b/sys/fs/fat/fat_write.c
@@ -0,0 +1,373 @@
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+//                            FAT16/32 File IO Library
+//                                    V2.6
+//                              Ultra-Embedded.com
+//                            Copyright 2003 - 2012
+//
+//                         Email: admin@ultra-embedded.com
+//
+//                                License: GPL
+//   If you would like a version with a more permissive license for use in
+//   closed source commercial applications please contact me for details.
+//-----------------------------------------------------------------------------
+//
+// This file is part of FAT File IO Library.
+//
+// FAT File IO Library is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// FAT File IO Library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with FAT File IO Library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+//-----------------------------------------------------------------------------
+//-----------------------------------------------------------------------------
+#include 
+#include "fat_defs.h"
+#include "fat_access.h"
+#include "fat_table.h"
+#include "fat_write.h"
+#include "fat_string.h"
+#include "fat_misc.h"
+
+#if FATFS_INC_WRITE_SUPPORT
+//-----------------------------------------------------------------------------
+// fatfs_add_free_space: Allocate another cluster of free space to the end
+// of a files cluster chain.
+//-----------------------------------------------------------------------------
+int fatfs_add_free_space(struct fatfs *fs, uint32 *startCluster, uint32 clusters)
+{
+    uint32 i;
+    uint32 nextcluster;
+    uint32 start = *startCluster;
+
+    // Set the next free cluster hint to unknown
+    if (fs->next_free_cluster != FAT32_LAST_CLUSTER)
+        fatfs_set_fs_info_next_free_cluster(fs, FAT32_LAST_CLUSTER);
+
+    for (i=0;irootdir_first_cluster, &nextcluster))
+        {
+            // Point last to this
+            fatfs_fat_set_cluster(fs, start, nextcluster);
+
+            // Point this to end of file
+            fatfs_fat_set_cluster(fs, nextcluster, FAT32_LAST_CLUSTER);
+
+            // Adjust argument reference
+            start = nextcluster;
+            if (i == 0)
+                *startCluster = nextcluster;
+        }
+        else
+            return 0;
+    }
+
+    return 1;
+}
+//-----------------------------------------------------------------------------
+// fatfs_allocate_free_space: Add an ammount of free space to a file either from
+// 'startCluster' if newFile = false, or allocating a new start to the chain if
+// newFile = true.
+//-----------------------------------------------------------------------------
+int fatfs_allocate_free_space(struct fatfs *fs, int newFile, uint32 *startCluster, uint32 size)
+{
+    uint32 clusterSize;
+    uint32 clusterCount;
+    uint32 nextcluster;
+
+    if (size==0)
+        return 0;
+
+    // Set the next free cluster hint to unknown
+    if (fs->next_free_cluster != FAT32_LAST_CLUSTER)
+        fatfs_set_fs_info_next_free_cluster(fs, FAT32_LAST_CLUSTER);
+
+    // Work out size and clusters
+    clusterSize = fs->sectors_per_cluster * FAT_SECTOR_SIZE;
+    clusterCount = (size / clusterSize);
+
+    // If any left over
+    if (size-(clusterSize*clusterCount))
+        clusterCount++;
+
+    // Allocated first link in the chain if a new file
+    if (newFile)
+    {
+        if (!fatfs_find_blank_cluster(fs, fs->rootdir_first_cluster, &nextcluster))
+            return 0;
+
+        // If this is all that is needed then all done
+        if (clusterCount==1)
+        {
+            fatfs_fat_set_cluster(fs, nextcluster, FAT32_LAST_CLUSTER);
+            *startCluster = nextcluster;
+            return 1;
+        }
+    }
+    // Allocate from end of current chain (startCluster is end of chain)
+    else
+        nextcluster = *startCluster;
+
+    if (!fatfs_add_free_space(fs, &nextcluster, clusterCount))
+            return 0;
+
+    return 1;
+}
+//-----------------------------------------------------------------------------
+// fatfs_find_free_dir_offset: Find a free space in the directory for a new entry
+// which takes up 'entryCount' blocks (or allocate some more)
+//-----------------------------------------------------------------------------
+static int fatfs_find_free_dir_offset(struct fatfs *fs, uint32 dirCluster, int entryCount, uint32 *pSector, uint8 *pOffset)
+{
+    struct fat_dir_entry *directoryEntry;
+    uint8 item=0;
+    uint16 recordoffset = 0;
+    uint8 i=0;
+    int x=0;
+    int possible_spaces = 0;
+    int start_recorded = 0;
+
+    // No entries required?
+    if (entryCount == 0)
+        return 0;
+
+    // Main cluster following loop
+    while (1)
+    {
+        // Read sector
+        if (fatfs_sector_reader(fs, dirCluster, x++, 0))
+        {
+            // Analyse Sector
+            for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++)
+            {
+                // Create the multiplier for sector access
+                recordoffset = FAT_DIR_ENTRY_SIZE * item;
+
+                // Overlay directory entry over buffer
+                directoryEntry = (struct fat_dir_entry*)(fs->currentsector.sector+recordoffset);
+
+                // LFN Entry
+                if (fatfs_entry_lfn_text(directoryEntry))
+                {
+                    // First entry?
+                    if (possible_spaces == 0)
+                    {
+                        // Store start
+                        *pSector = x-1;
+                        *pOffset = item;
+                        start_recorded = 1;
+                    }
+
+                    // Increment the count in-case the file turns
+                    // out to be deleted...
+                    possible_spaces++;
+                }
+                // SFN Entry
+                else
+                {
+                    // Has file been deleted?
+                    if (fs->currentsector.sector[recordoffset] == FILE_HEADER_DELETED)
+                    {
+                        // First entry?
+                        if (possible_spaces == 0)
+                        {
+                            // Store start
+                            *pSector = x-1;
+                            *pOffset = item;
+                            start_recorded = 1;
+                        }
+
+                        possible_spaces++;
+
+                        // We have found enough space?
+                        if (possible_spaces >= entryCount)
+                            return 1;
+
+                        // Else continue counting until we find a valid entry!
+                    }
+                    // Is the file entry empty?
+                    else if (fs->currentsector.sector[recordoffset] == FILE_HEADER_BLANK)
+                    {
+                        // First entry?
+                        if (possible_spaces == 0)
+                        {
+                            // Store start
+                            *pSector = x-1;
+                            *pOffset = item;
+                            start_recorded = 1;
+                        }
+
+                        // Increment the blank entries count
+                        possible_spaces++;
+
+                        // We have found enough space?
+                        if (possible_spaces >= entryCount)
+                            return 1;
+                    }
+                    // File entry is valid
+                    else
+                    {
+                        // Reset all flags
+                        possible_spaces = 0;
+                        start_recorded = 0;
+                    }
+                }
+            } // End of for
+        } // End of if
+        // Run out of free space in the directory, allocate some more
+        else
+        {
+            uint32 newCluster;
+
+            // Get a new cluster for directory
+            if (!fatfs_find_blank_cluster(fs, fs->rootdir_first_cluster, &newCluster))
+                return 0;
+
+            // Add cluster to end of directory tree
+            if (!fatfs_fat_add_cluster_to_chain(fs, dirCluster, newCluster))
+                return 0;
+
+            // Erase new directory cluster
+            memset(fs->currentsector.sector, 0x00, FAT_SECTOR_SIZE);
+            for (i=0;isectors_per_cluster;i++)
+            {
+                if (!fatfs_write_sector(fs, newCluster, i, 0))
+                    return 0;
+            }
+
+            // If non of the name fitted on previous sectors
+            if (!start_recorded)
+            {
+                // Store start
+                *pSector = (x-1);
+                *pOffset = 0;
+                start_recorded = 1;
+            }
+
+            return 1;
+        }
+    } // End of while loop
+
+    return 0;
+}
+//-----------------------------------------------------------------------------
+// fatfs_add_file_entry: Add a directory entry to a location found by FindFreeOffset
+//-----------------------------------------------------------------------------
+int fatfs_add_file_entry(struct fatfs *fs, uint32 dirCluster, char *filename, char *shortfilename, uint32 startCluster, uint32 size, int dir)
+{
+    uint8 item=0;
+    uint16 recordoffset = 0;
+    uint8 i=0;
+    uint32 x=0;
+    int entryCount;
+    struct fat_dir_entry shortEntry;
+    int dirtySector = 0;
+
+    uint32 dirSector = 0;
+    uint8 dirOffset = 0;
+    int foundEnd = 0;
+
+    uint8 checksum;
+    uint8 *pSname;
+
+    // No write access?
+    if (!fs->disk_io.write_media)
+        return 0;
+
+#if FATFS_INC_LFN_SUPPORT
+    // How many LFN entries are required?
+    // NOTE: We always request one LFN even if it would fit in a SFN!
+    entryCount = fatfs_lfn_entries_required(filename);
+    if (!entryCount)
+        return 0;
+#else
+    entryCount = 0;
+#endif
+
+    // Find space in the directory for this filename (or allocate some more)
+    // NOTE: We need to find space for at least the LFN + SFN (or just the SFN if LFNs not supported).
+    if (!fatfs_find_free_dir_offset(fs, dirCluster, entryCount + 1, &dirSector, &dirOffset))
+        return 0;
+
+    // Generate checksum of short filename
+    pSname = (uint8*)shortfilename;
+    checksum = 0;
+    for (i=11; i!=0; i--) checksum = ((checksum & 1) ? 0x80 : 0) + (checksum >> 1) + *pSname++;
+
+    // Start from current sector where space was found!
+    x = dirSector;
+
+    // Main cluster following loop
+    while (1)
+    {
+        // Read sector
+        if (fatfs_sector_reader(fs, dirCluster, x++, 0))
+        {
+            // Analyse Sector
+            for (item = 0; item < FAT_DIR_ENTRIES_PER_SECTOR; item++)
+            {
+                // Create the multiplier for sector access
+                recordoffset = FAT_DIR_ENTRY_SIZE * item;
+
+                // If the start position for the entry has been found
+                if (foundEnd==0)
+                    if ( (dirSector==(x-1)) && (dirOffset==item) )
+                        foundEnd = 1;
+
+                // Start adding filename
+                if (foundEnd)
+                {
+                    if (entryCount==0)
+                    {
+                        // Short filename
+                        fatfs_sfn_create_entry(shortfilename, size, startCluster, &shortEntry, dir);
+
+#if FATFS_INC_TIME_DATE_SUPPORT
+                        // Update create, access & modify time & date
+                        fatfs_update_timestamps(&shortEntry, 1, 1, 1);
+#endif
+
+                        memcpy(&fs->currentsector.sector[recordoffset], &shortEntry, sizeof(shortEntry));
+
+                        // Writeback
+                        return fs->disk_io.write_media(fs->currentsector.address, fs->currentsector.sector, 1);
+                    }
+#if FATFS_INC_LFN_SUPPORT
+                    else
+                    {
+                        entryCount--;
+
+                        // Copy entry to directory buffer
+                        fatfs_filename_to_lfn(filename, &fs->currentsector.sector[recordoffset], entryCount, checksum);
+                        dirtySector = 1;
+                    }
+#endif
+                }
+            } // End of if
+
+            // Write back to disk before loading another sector
+            if (dirtySector)
+            {
+                if (!fs->disk_io.write_media(fs->currentsector.address, fs->currentsector.sector, 1))
+                    return 0;
+
+                dirtySector = 0;
+            }
+        }
+        else
+            return 0;
+    } // End of while loop
+
+    return 0;
+}
+#endif
diff --git a/sys/fs/fat/fat_write.h b/sys/fs/fat/fat_write.h
new file mode 100644
index 0000000..5558a86
--- /dev/null
+++ b/sys/fs/fat/fat_write.h
@@ -0,0 +1,14 @@
+#ifndef __FAT_WRITE_H__
+#define __FAT_WRITE_H__
+
+#include "fat_defs.h"
+#include "fat_opts.h"
+
+//-----------------------------------------------------------------------------
+// Prototypes
+//-----------------------------------------------------------------------------
+int fatfs_add_file_entry(struct fatfs *fs, uint32 dirCluster, char *filename, char *shortfilename, uint32 startCluster, uint32 size, int dir);
+int fatfs_add_free_space(struct fatfs *fs, uint32 *startCluster, uint32 clusters);
+int fatfs_allocate_free_space(struct fatfs *fs, int newFile, uint32 *startCluster, uint32 size);
+
+#endif
diff --git a/sys/fs/fat/version.txt b/sys/fs/fat/version.txt
new file mode 100644
index 0000000..5a00a98
--- /dev/null
+++ b/sys/fs/fat/version.txt
@@ -0,0 +1 @@
+2.6.11
diff --git a/sys/i386/trap.c b/sys/i386/trap.c
index 60f0c65..de1a2c4 100644
--- a/sys/i386/trap.c
+++ b/sys/i386/trap.c
@@ -83,7 +83,7 @@
   kprintf("esi: %08lx   edi: %08lx   ebp: %08lx   esp: %08lx\n", regs->tf_esi, regs->tf_edi, regs->tf_ebp, esp);
   kprintf("cs:  0x%X ds: 0x%X  es:  0x%X fs: 0x%X gs: 0x%X ss: 0x%X\n", regs->tf_cs, regs->tf_ds, regs->tf_es, regs->tf_fs, regs->tf_gs, ss);
   kprintf("cr0: 0x%X, cr2: 0x%X, cr3: 0x%X, cr4: 0x%X\n", rcr0(), rcr2(), rcr3(), rcr4());
-  
+
   store_TR(i);
   kprintf("Process %s (pid: %i, process nr: %d, stackpage=%08lx)\nStack:", _current->name, _current->id, 0xffff & i, esp);
 
@@ -105,17 +105,18 @@
   trap_code = frame->tf_trapno;
 
   cr2 = rcr2();
-  kprintf("CR2: 0x%X(0x%X)[0x%X]", cr2,_current->tss.eip,_current->tss.ldt);
+  kprintf("CR2: 0x%X(0x%X)[0x%X]", cr2, _current->tss.eip, _current->tss.ldt);
   if (_current->id == 7)
-    while(1) asm("nop");
+    while (1)
+      asm("nop");
 
   if ((frame->tf_eflags & PSL_I) == 0) {
     if (SEL_GET_PL(frame->tf_cs) == SEL_PL_USER || (frame->tf_eflags & PSL_VM)) {
-      kpanic( "INT OFF! USER" );
+      kpanic("INT OFF! USER");
       die_if_kernel("TEST", frame, 0x100);
     }
     else {
-      kpanic( "INT OFF! KERN[0x%X]", trap_code );
+      kpanic("INT OFF! KERN[0x%X]", trap_code);
       die_if_kernel("TEST", frame, 0x200);
     }
   }
diff --git a/sys/kernel/descrip.c b/sys/kernel/descrip.c
index f705e23..e025559 100644
--- a/sys/kernel/descrip.c
+++ b/sys/kernel/descrip.c
@@ -33,7 +33,6 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 
 static struct file *kern_files = 0x0;
@@ -41,10 +40,6 @@
 int fcntl(struct thread *td, struct fcntl_args *uap) {
   struct file *fp = 0x0;
 
-#ifdef DEBUG
-  kprintf("[%s:%i]",__FILE__,__LINE__);
-#endif
-
   if (td->o_files[uap->fd] == 0x0) {
     kprintf("ERROR!!!\n");
     return (-1);
@@ -99,6 +94,8 @@
   return (0x0);
 }
 
+#include 
+
 int fdestroy(struct thread *td, struct file *fp, int fd) {
   int error = 0;