From a65fe3315cbc535ea6c902d1e74fd422b72975d5 Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Wed, 3 May 2017 12:39:05 +0100 Subject: [PATCH] FatFs: Update to release R0.12c. --- firmware/application/ffconf.h | 21 +- .../ext/fatfs/doc/00index_e.html | 15 +- .../ext/fatfs/doc/00index_j.html | 15 +- .../chibios-portapack/ext/fatfs/doc/css_e.css | 3 +- .../chibios-portapack/ext/fatfs/doc/css_j.css | 3 +- .../ext/fatfs/doc/en/appnote.html | 24 +- .../ext/fatfs/doc/en/dread.html | 4 +- .../ext/fatfs/doc/en/dstat.html | 2 +- .../ext/fatfs/doc/en/dwrite.html | 2 +- .../ext/fatfs/doc/en/expand.html | 17 +- .../ext/fatfs/doc/en/fdisk.html | 7 +- .../ext/fatfs/doc/en/lseek.html | 5 +- .../ext/fatfs/doc/en/mkfs.html | 8 +- .../ext/fatfs/doc/en/rc.html | 11 +- .../ext/fatfs/doc/en/readdir.html | 2 +- .../ext/fatfs/doc/en/sdir.html | 2 +- .../ext/fatfs/doc/en/sfileinfo.html | 2 +- .../ext/fatfs/doc/ja/appnote.html | 11 +- .../ext/fatfs/doc/ja/expand.html | 8 +- .../ext/fatfs/doc/ja/fdisk.html | 7 +- .../ext/fatfs/doc/ja/lseek.html | 5 +- .../ext/fatfs/doc/ja/rc.html | 13 +- .../ext/fatfs/doc/ja/sfileinfo.html | 2 +- .../ext/fatfs/doc/res/app4.c | 10 +- .../ext/fatfs/doc/res/layers3.png | Bin 2379 -> 0 bytes .../ext/fatfs/doc/res/mkfatimg.zip | Bin 686662 -> 686683 bytes .../ext/fatfs/doc/res/mkfs.xls | Bin 3238912 -> 3238912 bytes .../ext/fatfs/doc/updates.txt | 8 +- .../ext/fatfs/src/00history.txt | 13 +- .../ext/fatfs/src/00readme.txt | 26 +- firmware/chibios-portapack/ext/fatfs/src/ff.c | 722 ++++++++++-------- firmware/chibios-portapack/ext/fatfs/src/ff.h | 25 +- .../ext/fatfs/src/ffconf_template.h | 265 ------- .../chibios-portapack/ext/fatfs/src/integer.h | 2 +- 34 files changed, 556 insertions(+), 704 deletions(-) delete mode 100644 firmware/chibios-portapack/ext/fatfs/doc/res/layers3.png delete mode 100644 firmware/chibios-portapack/ext/fatfs/src/ffconf_template.h diff --git a/firmware/application/ffconf.h b/firmware/application/ffconf.h index 44242d37..041cd7cd 100644 --- a/firmware/application/ffconf.h +++ b/firmware/application/ffconf.h @@ -5,7 +5,7 @@ / FatFs - FAT file system module configuration file /---------------------------------------------------------------------------*/ -#define _FFCONF 68020 /* Revision ID */ +#define _FFCONF 68300 /* Revision ID */ /*---------------------------------------------------------------------------/ / Function Configurations @@ -76,7 +76,7 @@ /* This option specifies the OEM code page to be used on the target system. / Incorrect setting of the code page can cause a file open failure. / -/ 1 - ASCII (No extended character. Non-LFN cfg. only) +/ 1 - ASCII (No support of extended character. Non-LFN cfg. only) / 437 - U.S. / 720 - Arabic / 737 - Greek @@ -151,7 +151,7 @@ /---------------------------------------------------------------------------*/ #define _VOLUMES 1 -/* Number of volumes (logical drives) to be used. */ +/* Number of volumes (logical drives) to be used. (1-10) */ #define _STR_VOLUME_ID 0 @@ -175,11 +175,11 @@ #define _MIN_SS 512 #define _MAX_SS 512 /* These options configure the range of sector size to be supported. (512, 1024, -/ 2048 or 4096) Always set both 512 for most systems, all type of memory cards and +/ 2048 or 4096) Always set both 512 for most systems, generic memory card and / harddisk. But a larger value may be required for on-board flash memory and some / type of optical media. When _MAX_SS is larger than _MIN_SS, FatFs is configured -/ to variable sector size and GET_SECTOR_SIZE command must be implemented to the -/ disk_ioctl() function. */ +/ to variable sector size and GET_SECTOR_SIZE command needs to be implemented to +/ the disk_ioctl() function. */ #define _USE_TRIM 0 @@ -207,7 +207,7 @@ #define _FS_TINY 0 /* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) -/ At the tiny configuration, size of file object (FIL) is reduced _MAX_SS bytes. +/ At the tiny configuration, size of file object (FIL) is shrinked _MAX_SS bytes. / Instead of private sector buffer eliminated from the file object, common sector / buffer in the file system object (FATFS) is used for the file data transfer. */ @@ -215,7 +215,7 @@ #define _FS_EXFAT 0 /* This option switches support of exFAT file system. (0:Disable or 1:Enable) / When enable exFAT, also LFN needs to be enabled. (_USE_LFN >= 1) -/ Note that enabling exFAT discards C89 compatibility. */ +/ Note that enabling exFAT discards ANSI C (C89) compatibility. */ #define _FS_NORTC 0 @@ -228,7 +228,7 @@ / defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR in local time. / To enable timestamp function (_FS_NORTC = 0), get_fattime() function need to be / added to the project to get current time form real-time clock. _NORTC_MON, -/ _NORTC_MDAY and _NORTC_YEAR have no effect. +/ _NORTC_MDAY and _NORTC_YEAR have no effect. / These options have no effect at read-only configuration (_FS_READONLY = 1). */ @@ -261,10 +261,11 @@ / / The _FS_TIMEOUT defines timeout period in unit of time tick. / The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*, -/ SemaphoreHandle_t and etc.. A header file for O/S definitions needs to be +/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be / included somewhere in the scope of ff.h. */ /* #include // O/S definitions */ + /*--- End of configuration options ---*/ diff --git a/firmware/chibios-portapack/ext/fatfs/doc/00index_e.html b/firmware/chibios-portapack/ext/fatfs/doc/00index_e.html index 905b7b8f..68e22b0f 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/00index_e.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/00index_e.html @@ -10,11 +10,11 @@ -FatFs - Generic FAT File System Module +FatFs - Generic FAT File System Module (R0.12c) -

FatFs - Generic FAT File System Module

+

FatFs - Generic FAT File System Module (R0.12c)


@@ -23,7 +23,7 @@

Features

    -
  • Windows compatible FAT/exFAT file system.
  • +
  • DOS/Windows compatible FAT/exFAT file system.
  • Platform independent. Easy to port.
  • Very small footprint for program code and work area.
  • Various configuration options to support for: @@ -44,6 +44,7 @@

    Application Interface

    layer +

    FatFs provides various file control functions for the applications as shown below.

    • File Access
        @@ -103,9 +104,9 @@
        -

        Device Control Interface

        +

        Media Access Interface

        layer -

        Since the FatFs module is a file system layer, it is completely separated from the physical devices, such as memory card, harddisk and any type of storage device. FatFs accesses the storage devices via a simple interface shown below. The low level device control module is not a part of FatFs module. It is provided by implementer. Also sample implementations for some platforms are available in the downloads.

        +

        Since the FatFs module is just a file system layer independent of platform and storage device. It is completely separated from the physical devices, such as memory card, harddisk and any type of storage device. The low level device control module is not a part of FatFs module and it needs to be provided by implementer. FatFs accesses the storage devices via a simple media access interface shown below. Also sample implementations for some platforms are available in the downloads.

        • disk_status - Get device status
        • disk_initialize - Initialize device
        • @@ -121,7 +122,7 @@

          Resources

          The FatFs module is a free software opened for education, research and development. You can use, modify and/or redistribute it for personal projects or commercial products without any restriction under your responsibility. For further information, refer to the application note.

            -
          • Read first: FatFs module application note July 10, 2016
          • +
          • Read first: FatFs module application note
          • Community: FatFs User Forum
          • FAT32 Specification by Microsoft↗ (The authorized document on FAT file system)
          • The basics of FAT file system [ja]
          • @@ -136,6 +137,6 @@
            -

            FatFs home page

            +

            FatFs Homepage

            diff --git a/firmware/chibios-portapack/ext/fatfs/doc/00index_j.html b/firmware/chibios-portapack/ext/fatfs/doc/00index_j.html index 51df31d5..02c927fb 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/00index_j.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/00index_j.html @@ -10,11 +10,11 @@ -FatFs 汎用FATファイルシステム モジュール +FatFs 汎用FATファイルシステム モジュール (R0.12c) -

            FatFs 汎用FATファイルシステム モジュール

            +

            FatFs 汎用FATファイルシステム モジュール (R0.12c)


            @@ -22,7 +22,7 @@

            FatFsは小規模な組み込みシステム向けの汎用FAT/exFATファイルシステム モジュールです。ANSI C(C89)準拠でハードウェア アーキテクチャには依存しないので、必要なワーク エリアが確保できれば、8051, PIC, AVR, SH, Z80, 68k, H8, ARMなど安価なマイコンでも使用可能です。このほか、FatFsを極小マイコン向けにシュリンクしたぷちFatFsもあります。

            FatFsモジュールの特徴

              -
            • Windows互換 FAT/exFATファイルシステム
            • +
            • DOS/Windows互換 FAT/exFATファイルシステム
            • プラットフォーム非依存
            • コンパクトなコードとRAM使用量
            • 多くの構成オプション: @@ -41,8 +41,9 @@
              -

              上位レイヤ インターフェース

              +

              アプリケーション インターフェース

              layer +

              FatFsモジュールは、上位レイヤに対して次に示すファイルAPIを提供します。

              • ファイル アクセス
                  @@ -102,9 +103,9 @@
                  -

                  下位レイヤ インターフェース

                  +

                  デバイス制御インターフェース

                  layer -

                  FatFsモジュールは、単なるファイルシステム レイヤなので、その下位のストレージ デバイス制御レイヤはそれに含まれません。それぞれのプラットフォームやストレージ デバイスに対応した制御レイヤは、インプリメンタによって提供される必要があります。FatFsモジュールは、下位レイヤに対し標準的には次のインターフェースを要求します。一部の拡張機能、たとえばOS関連機能を有効にしたときは、加えてプロセス/メモリ操作関数なども必要になります。サンプル プロジェクトに下位レイヤの実装例を示します。

                  +

                  FatFsモジュールは、プラットフォームから独立した単なるファイルシステム レイヤです。ストレージ デバイス(例えばメモリ カード)の制御機能はFatFsの構成部分ではないので、インプリメンタによって提供される必要があります。FatFsモジュールは、下位レイヤに対し標準的には次のインターフェースを要求します。一部の拡張機能(たとえばOS関連機能)を利用するときは、これらに加えてプロセス/メモリ操作関数なども必要になります。サンプル プロジェクトに下位レイヤの実装例を示します。

                  • disk_status - デバイスの状態取得
                  • disk_initialize - デバイスの初期化
                  • @@ -120,7 +121,7 @@

                    資料

                    FatFsモジュールはフリー ソフトウェアとして教育・研究・開発用に公開しています。どのような利用目的(個人利用から商用まで)でも使用・改変・配布について一切の制限はありませんが、全て利用者の責任の下での利用とします。詳しくはアプリケーション ノートを参照してください。

                      -
                    • 最初に読め: FatFsモジュール アプリケーション ノート 2016. 9. 4
                    • +
                    • 最初に読め: FatFsモジュール アプリケーション ノート
                    • コミュニティ: FatFsユーザ フォーラム
                    • FATファイルシステム仕様 by Microsoft↗ (The reference document on FAT file system)
                    • FATファイルシステム概要 (↑を読むためのガイド)
                    • diff --git a/firmware/chibios-portapack/ext/fatfs/doc/css_e.css b/firmware/chibios-portapack/ext/fatfs/doc/css_e.css index 99c6714a..0813d7be 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/css_e.css +++ b/firmware/chibios-portapack/ext/fatfs/doc/css_e.css @@ -14,6 +14,7 @@ strong {} pre {border: 1px dashed gray; margin: 0.5em 1em; padding: 0.5em; line-height: 1.2em; font-size: 85%; font-family: "Consolas", "Courier New", monospace; background-color: white;} pre span.c {color: green;} pre span.k {color: blue;} +pre span.b {font-weight: bold;} pre span.arg {font-style: italic;} tt {margin: 0 0.2em; font-size: 0.85em; font-family: "Consolas", "Courier New", monospace; } tt.arg {font-style: italic;} @@ -24,7 +25,7 @@ dl {margin: 0.5em 1em;} dd {margin: 0 2em;} dt {font-size: 0.85em; font-family: "Consolas", "Courier New", monospace;} dl.par dt {margin: 0.5em 0 0 0 ; font-style: italic; } -dl.ret dt {margin: 0.5em 0 0 0 ; font-size: 0.85em; font-family: "Consolas", "Courier New", monospace;} +dl.ret dt {margin: 0.5em 0 0 0 ; font-size: 0.85em; font-family: "Consolas", "Courier New", monospace; font-weight: bold; } hr {border-width: 1px; margin: 1em;} div.abst {font-family: sans-serif;} div.para {clear: both; font-family: serif;} diff --git a/firmware/chibios-portapack/ext/fatfs/doc/css_j.css b/firmware/chibios-portapack/ext/fatfs/doc/css_j.css index 3b1a9646..77b634e3 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/css_j.css +++ b/firmware/chibios-portapack/ext/fatfs/doc/css_j.css @@ -17,6 +17,7 @@ strong {} pre {border: 1px dashed gray; margin: 0.5em 1em; padding: 0.5em; line-height: 1.2em; letter-spacing: 0; font-size: 0.85em; font-family: "Consolas", "Courier New", "lr SVbN", monospace; background-color: white;} pre span.c {color: green;} pre span.k {color: blue;} +pre span.b {font-weight: bold;} pre span.arg {font-style: italic;} tt {margin: 0 0.2em; letter-spacing: 0; font-size: 0.85em; font-family: "Consolas", "Courier New", "lr SVbN", monospace;} tt.arg {font-style: italic;} @@ -27,7 +28,7 @@ dl {margin: 0.5em 1em;} dd {margin: 0em 2em;} dt {font-size: 0.85em; font-family: "Consolas", "Courier New", "lr SVbN", monospace;} dl.par dt {margin: 0.5em 0 0 0 ; font-style: italic; letter-spacing: 0;} -dl.ret dt {margin: 0.5em 0 0 0 ; font-size: 0.85em; font-family: "Consolas", "Courier New", "lr SVbN", monospace; letter-spacing: 0; } +dl.ret dt {margin: 0.5em 0 0 0 ; font-size: 0.85em; font-family: "Consolas", "Courier New", "lr SVbN", monospace; letter-spacing: 0; font-weight: bold; } hr {border-width: 1px; margin: 1em;} div.abst {font-family: "lr oSVbN",sans-serif;} div.para {clear: both; font-family: "lr o",serif;} diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/appnote.html b/firmware/chibios-portapack/ext/fatfs/doc/en/appnote.html index 5acfdeb3..34d01cf3 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/appnote.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/appnote.html @@ -64,7 +64,7 @@ The FatFs module assumes that size of char/short/long

                      Limits

                        -
                      • File system type: FAT12, FAT16, FAT32(r0.0) and exFAT(r1.0).
                      • +
                      • File system type: FAT, FAT32(r0.0) and exFAT(r1.0).
                      • Number of open files: Unlimited. (depends on available memory)
                      • Number of volumes: Upto 10.
                      • Volume size: Upto 2 TiB at 512 bytes/sector.
                      • @@ -144,7 +144,7 @@ And other options are left unchanged from original setting.

                        Long File Name

                        -

                        FatFs module supports long file name (LFN). The two different file names, short file name (SFN) and LFN, of a file is transparent on the API except for f_readdir function. The support for LFN is disabled by default. To enable the LFN, set _USE_LFN to 1, 2 or 3, and add option/unicode.c to the project. The LFN requiers a certain working buffer in addition. The buffer size can be configured by _MAX_LFN according to the available memory. The length of an LFN will be up to 255 characters, so that the _MAX_LFN should be set to 255 for all file names. If the size of working buffer is insufficient for the input file name, the file function fails with FR_INVALID_NAME. When use any re-entry to the API with LFN is enabled, _USE_LFN must be set to 2 or 3. In this case, the file function allocates the working buffer on the stack or heap. The working buffer occupies (_MAX_LFN + 1) * 2 bytes and additional 608 bytes when exFAT enabled.

                        +

                        FatFs module supports long file name (LFN). The two different file names, short file name (SFN) and LFN, of a file is transparent on the API except for f_readdir function. The support for LFN is disabled by default. To enable the LFN, set _USE_LFN to 1, 2 or 3, and add option/unicode.c to the project. The LFN requiers a certain working buffer in addition. The buffer size can be configured by _MAX_LFN according to the available memory. The length of an LFN will be up to 255 characters, so that the _MAX_LFN should be set to 255 for all file names. If the size of working buffer is insufficient for the input file name, the file function fails with FR_INVALID_NAME. When use any re-entry to the API with LFN is enabled, _USE_LFN must be set to 2 or 3. In this case, the file function allocates the working buffer on the stack or heap. The working buffer occupies (_MAX_LFN + 1) * 2 bytes and additional (_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled.

                        @@ -165,22 +165,22 @@ And other options are left unchanged from original setting.

                        exFAT File System

                        -

                        The exFAT (Microsoft's Extended File Allocation Table) file system is a replacement of the FAT file system which has been widely used in the embedded systems and consumer devices. It is adopted by SDA (SD Association) as a recommended file system for high capacity SD cards (>32GB) and they are being shipped with this format, so that the exFAT will soon become one of the standard file systems for removable media.

                        -

                        The exFAT file system allows the file size larger than 4 GiB limit what FAT file system allows upto and some file system overhead, especially file allocation delay, are reduced as well. This feature improves the write throughput to the file. However a problem on the current implementation of FatFs is that write throughput at writing to the growing edge of the fragmented file gets less than the throughput on the FAT volume. Pre-allocating a contiguous block with f_expand function may be a workaround of this problem.

                        -

                        Note that the exFAT is a patent of Microsoft Corporation. The exFAT function of FatFs is an implementation based on US. Pat. App. Pub. No. 2009/0164440 A1. FatFs module can swich the exFAT on/off by configuration option. When enable the exFAT on the commercial products, you will need to be licensed by Microsoft depends on the final destination of the products.

                        -

                        Remark: Enabling exFAT discards C89 compatibility because of need for 64-bit integer type.

                        +

                        The exFAT (Microsoft's Extended File Allocation Table) file system is a replacement of the FAT file system which has been widely used in the embedded systems and consumer devices. It is adopted by SDA (SD Association) as a recommended file system for high capacity SD cards (>32GB) and they are being shipped with this format, so that the exFAT become one of the standard file systems for removable media as well as FAT. The exFAT file system allows the file size larger than 4 GiB limit what FAT file system allows upto and some file system overhead, especially cluster allocation delay, are reduced as well. This feature improves the write throughput to the file.

                        +

                        Note that the exFAT is a patent of Microsoft Corporation. The exFAT function of FatFs is an implementation based on US. Pat. App. Pub. No. 2009/0164440 A1. FatFs module can swich the exFAT on/off by configuration option. When enable the exFAT on the commercial products, you will need to be licensed by Microsoft depends on the final destination of the products.

                        +

                        Remark: Enabling exFAT discards ANSI C (C89) compatibility because of need for 64-bit integer type.

                        +

                        Re-entrancy

                        -

                        The file operations to the different volume is always re-entrant regardless of configurations except when LFN enabled with static working buffer. It can work simultaneously without any mutual exclusion.

                        -

                        The file operations to the same volume is not re-entrant but it can also be configured thread-safe by option _FS_REENTRANT. It enables to control exclusive use of each file system object. In this case, also the OS dependent synchronization object control functions, ff_cre_syncobj/ff_del_syncobj/ff_req_grant/ff_rel_grant, needed to be added to the project. There are some examples in the option/syscall.c.

                        +

                        The file operations to the different volume each other is always re-entrant regardless of configurations except when LFN enabled with static working buffer. It can work simultaneously without any mutual exclusion.

                        +

                        The file operations to the same volume is not re-entrant. It can also be configured thread-safe by option _FS_REENTRANT. It enables to control exclusive use of each file system object. In this case, also the OS dependent synchronization object control functions, ff_cre_syncobj/ff_del_syncobj/ff_req_grant/ff_rel_grant, needed to be added to the project. There are some examples in the option/syscall.c.

                        When a file function is called while the volume is being accessed by other task, the file function to the volume will be suspended until that task leaves the file function. If the wait time exceeded a period defined by _TIMEOUT, the file function will abort with FR_TIMEOUT. The timeout function might not be supported on the some RTOSs.

                        -

                        There is an exception on the re-entrancy for f_mount/f_mkfs/f_fdisk function. These volume management functions are not re-entrant to the same volume and corresponding physical drive. When use these functions, other tasks need to avoid to access the volume.

                        -

                        Note that this section describes on the re-entrancy of the FatFs module itself. The _FS_REENTRANT controls only exclusive use of each file system object and it does not that prevent to re-enter the low level disk functions. For example, only disk_status function can be re-entered at single volume system and any disk function can be re-entered at multiple volume system. Thus the low level disk I/O layer must be always thread-safe when any FatFs API is re-entered by two or more tasks.

                        +

                        There is an exception on the re-entrancy for f_mount/f_mkfs/f_fdisk function. These volume management functions are not re-entrant on the same volume and corresponding physical drive. When use these functions, other tasks need to avoid to access the volume.

                        +

                        Note that this section describes on the re-entrancy of the FatFs module itself. The _FS_REENTRANT controls only exclusive use of each file system object and it does not that prevent re-entering the low level disk functions. For example, only disk_status function is re-entered at single volume system and every disk function is re-entered at multiple volume system. Thus the low level disk I/O layer must be always thread-safe when FatFs API is re-entered by two or more tasks.

                        -

                        Duplicated File Access

                        +

                        Duplicated File Open

                        FatFs module does not support the read/write collision control of duplicated open to a file. The duplicated open is permitted only when each of open method to a file is read mode. The duplicated open with one or more write mode to a file is always prohibited, and also open file must not be renamed or deleted. A violation of these rules can cause data colluption.

                        The file lock control can be enabled by _FS_LOCK option. The value of option defines the number of open objects to manage simultaneously. In this case, if any open, rename or remove that violating the file shareing rule that described above is attempted, the file function will rejected with FR_LOCKED. If number of open objects, files and sub-directories, is equal to _FS_LOCK, an extra f_open/f_opendir function will fail with FR_TOO_MANY_OPEN_FILES.

                        @@ -274,7 +274,7 @@ Figure 5. Minimized critical section
                        / by use of this software. /----------------------------------------------------------------------------*/ -

                        Therefore FatFs license is one of the BSD-style licenses but there is a significant feature. FatFs is mainly intended for embedded systems. In order to extend the usability for commercial products, the redistributions of FatFs in binary form, such as embedded code, binary library and any forms without source code, does not need to include about FatFs in the documentations. This is equivalent to the 1-clause BSD license. Of course FatFs is compatible with the most open source software licenses including GNU GPL. When you redistribute the FatFs source code with any changes or create a fork, the license can also be changed to GNU GPL, BSD-style license or any open source software licenses that not conflict with FatFs license.

                        +

                        Therefore FatFs license is one of the BSD-style licenses but there is a significant feature. FatFs is mainly intended for embedded systems. In order to extend the usability for commercial products, the redistributions of FatFs in binary form, such as embedded code, binary library and any forms without source code, does not need to include about FatFs in the documentations. This is equivalent to the 1-clause BSD license. Of course FatFs is compatible with the most of open source software licenses including GNU GPL. When you redistribute the FatFs source code with any changes or create a fork, the license can also be changed to GNU GPL, BSD-style license or any open source software license that not conflict with FatFs license.

                        Return Home

                        diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/dread.html b/firmware/chibios-portapack/ext/fatfs/doc/en/dread.html index b7674a16..b4594c7d 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/dread.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/dread.html @@ -60,8 +60,8 @@ DRESULT disk_read (

                        The memory address specified by buff is not that always aligned to word boundary because the argument is defined as BYTE*. The unaligned read/write request can occure at direct transfer. If the bus architecture, especially DMA controller, does not allow unaligned memory access, it should be solved in this function. There are some workarounds described below to avoid this issue.

                        • Convert word transfer to byte transfer in this function if needed. - Recommended.
                        • -
                        • On the f_read calls, avoid long read request that includes a whole of sector. - Any direct transfer never occures.
                        • -
                        • On the f_read calls, make sure that (((UINT)data & 3) == (f_tell(fp) & 3)) is true. - Word alignment of buff is guaranteed.
                        • +
                        • On the f_read() calls, avoid long read request that includes a whole of sector. - Any direct transfer never occures.
                        • +
                        • On the f_read(fp, data, btw, bw) calls, make sure that (((UINT)data & 3) == (f_tell(fp) & 3)) is true. - Word alignment of buff is guaranteed.

                        Generally, a multiple sector transfer request must not be split into single sector transactions to the storage device, or you will not get good read throughput.

                        diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/dstat.html b/firmware/chibios-portapack/ext/fatfs/doc/en/dstat.html index 78508ba8..7092da7c 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/dstat.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/dstat.html @@ -35,7 +35,7 @@ DSTATUS disk_status (

                        The current drive status is returned in combination of status flags described below. FatFs refers only STA_NOINIT and STA_PROTECT.

                        STA_NOINIT
                        -
                        Indicates that the device is not initialized and not ready to work. This flag is set on system reset, media removal or failure of disk_initialize function. It is cleared on disk_initialize function succeeded. Any media change that occurs asynchronously must be captured and reflect it to the status flags, or auto-mount function will not work correctly. If the system does not support media change detection, application program needs to force de-initialize the file system object and re-mount the volume with f_mount function after each media change.
                        +
                        Indicates that the device is not initialized and not ready to work. This flag is set on system reset, media removal or failure of disk_initialize function. It is cleared on disk_initialize function succeeded. Any media change that occurs asynchronously must be captured and reflect it to the status flags, or auto-mount function will not work correctly. If the system does not support media change detection, application program needs to explicitly re-mount the volume with f_mount function after each media change.
                        STA_NODISK
                        Indicates that no medium in the drive. This is always cleared at fixed disk drive. Note that FatFs does not refer this flag.
                        STA_PROTECT
                        diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/dwrite.html b/firmware/chibios-portapack/ext/fatfs/doc/en/dwrite.html index b99eccdc..a8c5ce8a 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/dwrite.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/dwrite.html @@ -60,7 +60,7 @@ DRESULT disk_write (

                        Description

                        The specified memory address is not that always aligned to word boundary because the type of pointer is defined as BYTE*. For more information, refer to the description of disk_read function.

                        Generally, a multiple sector transfer request must not be split into single sector transactions to the storage device, or you will never get good write throughput.

                        -

                        FatFs expects delayed write function of the disk control layer. The write operation to the media does not need to be completed when return from this function by what write operation is in progress or data is only stored into the write-back cache. But write data on the buff is invalid after return from this function. The write completion request is done by CTRL_SYNC command of disk_ioctl function. Therefore, if a delayed write function is implemented, the write throughput will be improved.

                        +

                        FatFs expects delayed write function of the disk control layer. The write operation to the media does not need to be completed when return from this function by what write operation is in progress or data is only stored into the write-back cache. But write data on the buff is invalid after return from this function. The write completion request is done by CTRL_SYNC command of disk_ioctl function. Therefore, if a delayed write function is implemented, the write throughput of the file system will be improved.

                        Remarks: Application program MUST NOT call this function, or FAT structure on the volume can be collapsed.

                        diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/expand.html b/firmware/chibios-portapack/ext/fatfs/doc/en/expand.html index 54f21d1b..8e40d3ca 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/expand.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/expand.html @@ -60,8 +60,8 @@ FRESULT f_expand (
                      • Not allowable file size. (>= 4GiB on FAT volume)
                      • When opt is 0, the function finds a contiguous data area and set it as suggested point for next allocation instead of allocating it to the file. The next cluster allocation is started at top of the contiguous area found by this function. Thus the write file is guaranteed be contiguous and no allocation delay until the size reaches that size at least unless any other changes to the volume is performed.

                        -

                        The contiguous file would have an advantage at time-critical read/write operations. It reduces some overheads in the file system and the storage media caused by random access due to fragmented file data. Especially FAT access for the contiguous file on the exFAT volume is completely eliminated and storage media will be accessed sequentially.

                        -

                        Also the contiguous file data can be easily accessed directly via low-level disk functions. But this is not recommended in consideration for future compatibility.

                        +

                        The contiguous file would have an advantage at time-critical read/write operations. It eliminates some overheads in the file system and the storage media caused by random access due to fragmented file data. Especially FAT access for the contiguous file on the exFAT volume is completely eliminated and storage media will be accessed sequentially.

                        +

                        Also the contiguous file can be easily accessed directly via low-level disk functions. But this is not recommended in consideration for future compatibility.

                        @@ -79,28 +79,29 @@ FRESULT f_expand ( res = f_open(fp = malloc(sizeof (FIL)), "file.dat", FA_WRITE|FA_CREATE_ALWAYS); if (res) { /* Check if the file has been opened */ free(fp); - ... + die("Failed to open the file."); } /* Alloacte a 100 MiB of contiguous area to the file */ res = f_expand(fp, 104857600, 1); if (res) { /* Check if the file has been expanded */ - ... + f_close(fp); free(fp); - ... + die("Failed to allocate contiguous area."); } + /* Now you have a contiguous file accessible with fp */
                        -    /* Accessing the file data directly via low-level disk functions */
                        +    /* Accessing the contiguous file via low-level disk functions */
                         
                             /* Get physical location of the file data */
                             drv = fp->obj.fs->drv;
                        -    sect = fp->obj.fs->database + fp->obj.fs->csize * (fp->obj.sclust - 2);
                        +    lba = fp->obj.fs->database + fp->obj.fs->csize * (fp->obj.sclust - 2);
                         
                             /* Write 2048 sectors from top of the file at a time */
                        -    res = disk_write(drv, buffer, sect, 2048);
                        +    res = disk_write(drv, buffer, lba, 2048);
                         
                         
                        diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/fdisk.html b/firmware/chibios-portapack/ext/fatfs/doc/en/fdisk.html index 8414f919..e86ec6c7 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/fdisk.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/fdisk.html @@ -62,15 +62,14 @@ FRESULT f_fdisk ( /* Volume management table defined by user (required when _MULTI_PARTITION == 1) */ PARTITION VolToPart[] = { - {0, 1}, /* Logical drive 0 ==> Physical drive 0, 1st partition */ - {0, 2}, /* Logical drive 1 ==> Physical drive 0, 2nd partition */ - {1, 0} /* Logical drive 2 ==> Physical drive 1, auto detection */ + {0, 1}, /* "0:" ==> Physical drive 0, 1st partition */ + {0, 2}, /* "1:" ==> Physical drive 0, 2nd partition */ + {1, 0} /* "2:" ==> Physical drive 1, auto detection */ };
                             /* Initialize a brand-new disk drive mapped to physical drive 0 */
                         
                        -    FATFS fs;
                             DWORD plist[] = {50, 50, 0, 0};  /* Divide drive into two partitions */
                             BYTE work[_MAX_SS];
                         
                        diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/lseek.html b/firmware/chibios-portapack/ext/fatfs/doc/en/lseek.html
                        index cf4f47e5..f631979a 100644
                        --- a/firmware/chibios-portapack/ext/fatfs/doc/en/lseek.html
                        +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/lseek.html
                        @@ -29,7 +29,7 @@ FRESULT f_lseek (
                         
                        fp
                        Pointer to the open file object.
                        ofs
                        -
                        Byte offset from top of the file. The data type FSIZE_t is an alias of either DWORD(32-bit) or QWORD(64-bit) depends on the configuration option _FS_EXFAT.
                        +
                        Byte offset from top of the file to set read/write pointer. The data type FSIZE_t is an alias of either DWORD(32-bit) or QWORD(64-bit) depends on the configuration option _FS_EXFAT.
                        @@ -48,7 +48,8 @@ FRESULT f_lseek (

                        Description

                        -

                        The f_lseek function moves the file read/write pointer of an open file. The offset can be specified in only origin from top of the file. When an offset beyond the file size is specified at write mode, the file size is expanded to the specified offset. The file data in the expanded area is undefined because no data is written to the file in this process. This is suitable to pre-allocate a cluster chain quickly, for fast write operation. When a contiguous data area needs to be allocated to the file, use f_expand function instead. After the f_lseek function succeeded, the current read/write pointer should be checked in order to make sure the read/write pointer has been moved correctry. In case of the read/write pointer is not the expected value, either of followings has been occured.

                        +

                        File read/write ponter in the open file object points the data byte to be read/written at next read/write operation. It advances as the number of bytes read/written. The f_lseek function moves the file read/write pointer without any read/write operation to the file.

                        +

                        When an offset beyond the file size is specified at write mode, the file size is expanded to the specified offset. The file data in the expanded area is undefined because no data is written to the file in this process. This is suitable to pre-allocate a data area to the file quickly for fast write operation. When a contiguous data area needs to be allocated to the file, use f_expand function instead. After the f_lseek function succeeded, the current read/write pointer should be checked in order to make sure the read/write pointer has been moved correctry. In case of the read/write pointer is not the expected value, either of followings has been occured.

                        • End of file. The specified ofs was clipped at end of the file because the file has been opened in read-only mode.
                        • Disk full. There is no free space on the volume to expand the file.
                        • diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/mkfs.html b/firmware/chibios-portapack/ext/fatfs/doc/en/mkfs.html index 180ffdf8..aba07b9e 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/mkfs.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/mkfs.html @@ -29,7 +29,7 @@ FRESULT f_mkfs (

                          Parameters

                          path
                          -
                          Pointer to the null-terminated string specifies the logical drive to be formatted. If there is no drive number in it, it means the default drive. The logical drive may or may not be mounted for the format process.
                          +
                          Pointer to the null-terminated string specifies the logical drive to be formatted. If it has no drive number in it, it means the default drive. The logical drive may or may not be mounted for the format process.
                          opt
                          Specifies the format option in combination of FM_FAT, FM_FAT32, FM_EXFAT and bitwise-or of these three, FM_ANY. FM_EXFAT is ignored when exFAT is not enabled. These flags specify which FAT type to be created on the volume. If two or more types are specified, one out of them will be selected depends on the volume size. The flag FM_SFD specifies to place the volume on the drive in SFD format.
                          au
                          @@ -37,7 +37,7 @@ FRESULT f_mkfs (
                          work
                          Pointer to the working buffer used for the format process.
                          len
                          -
                          Size of the working buffer in unit of byte. It needs to be the sector size at least. Plenty of working buffer reduces number of write transaction to the device and the format process will be finished quickly.
                          +
                          Size of the working buffer in unit of byte. It needs to be the sector size at least. Plenty of working buffer reduces number of write transactions to the drive and the format process will be finished quickly.
                        @@ -57,9 +57,9 @@ FRESULT f_mkfs (

                        Description

                        The FAT sub-type, FAT12/FAT16/FAT32, of FAT volume except exFAT is determined by only number of clusters on the volume and nothing else, according to the FAT specification issued by Microsoft. Thus which FAT sub-type is selected, is depends on the volume size and the specified cluster size. In case of the combination of FAT type and cluter size specified by argument cannot be valid on the volume, the function will fail with FR_MKFS_ABORTED.

                        -

                        The allocation unit, also called 'cluster', is a unit of disk space allocation for files. When the size of allocation unit is 32768 bytes, a file with 100 bytes in size occupies 32768 bytes of disk space. The space efficiency of disk usage gets worse as increasing size of allocation unit, but, on the other hand, the read/write performance increases as the size of allocation unit. Therefore the allocation unit is a trade-off between space efficiency and performance. For the large storages in GB order, 32768 bytes or larger cluster (this is automatically selected by default) is recommended for most case unless extremely many files are created on a volume.

                        +

                        The allocation unit, also called 'cluster', is a unit of disk space allocation for files. When the size of allocation unit is 32768 bytes, a file with 100 bytes in size occupies 32768 bytes of disk space. The space efficiency of disk usage gets worse as increasing size of allocation unit, but, on the other hand, the read/write performance increases as the size of allocation unit. Therefore the size of allocation unit is a trade-off between space efficiency and performance. For the large storages in GB order, 32768 bytes or larger cluster (this is automatically selected by default) is recommended for most case unless extremely many small files are created on a volume.

                        There are two disk formats, FDISK and SFD. The FDISK format is usually used for harddisk, MMC, SDC, CFC and U Disk. It can divide a physical drive into one or more partitions with a partition table on the MBR (maser boot record, the first sector of the physical drive). The SFD (super-floppy disk) is non-partitioned disk format. The FAT volume starts at the first sector of the physical drive without any disk partitioning. It is usually used for floppy disk, Microdrive, optical disk and most type of super-floppy media. Some systems support only either one of two formats and other is not supported.

                        -

                        When FM_SFD is not specified, a primary partition occupies whole drive space is created and then the FAT volume is created in it. When FM_SFD is specified, the FAT volume occupies from the first sector of the drive is created.

                        +

                        When FM_SFD is not specified (the volume is bound to a physical drive), a primary partition occupies whole drive space is created and then the FAT volume is created in it. When FM_SFD is specified, the FAT volume occupies from the first sector of the drive is created.

                        If the logical drive to be formatted is bound to the specific partition (1-4) by support of multiple partition, _MULTI_PARTITION, the FAT volume is created into the partition and FM_SFD flag is ignored. The physical drive needs to be partitioned with f_fdisk function or any other partitioning tools prior to create the FAT volume with this function.

                        diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/rc.html b/firmware/chibios-portapack/ext/fatfs/doc/en/rc.html index 0e45fbee..89e650d3 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/rc.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/rc.html @@ -19,7 +19,7 @@
                        The function succeeded.
                        FR_DISK_ERR
                        -
                        An unrecoverable hard error occured in the lower layer, disk_read, disk_write or disk_ioctl function.
                        Note that if once this error occured at any operation to an open file, the file object is aborted and all operations to the file except for close will be rejected.
                        +
                        The lower layer, disk_read, disk_write or disk_ioctl function, reported that an unrecoverable hard error occured.
                        Note that if once this error occured at any operation to an open file, the file object is aborted and all operations to the file except for close will be rejected.
                        FR_INT_ERR
                        Assertion failed. An insanity is detected in the internal process. One of the following possibilities is suspected. @@ -32,7 +32,14 @@ Note that if once this error occured at any operation to an open file, the file
                        FR_NOT_READY
                        -
                        The storage device cannot work due to a failure of disk_initialize function due to no medium or any other reason.
                        +
                        The lower layer, disk_initialize function, reported that the storage device could not be got ready to work. One of the following possibilities is suspected. +
                          +
                        • No medium in the drive.
                        • +
                        • Wrong lower layer implementation for the storage device.
                        • +
                        • Wrong hardware configuration.
                        • +
                        • The storage device is broken.
                        • +
                        +
                        FR_NO_FILE
                        Could not find the file.
                        diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/readdir.html b/firmware/chibios-portapack/ext/fatfs/doc/en/readdir.html index 235beee7..6d79bd8e 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/readdir.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/readdir.html @@ -55,7 +55,7 @@ FRESULT f_readdir (
                      • Setting of _MAX_LFN is insufficient for the long file name. (Not the case at _MAX_LFN == 255)
                      • The long file name contains any character not allowed in ANSI/OEM code. (Not the case at _LFN_UNICODE == 1)
                      • -

                        There is a problem on reading a directory of exFAT volume. The exFAT does not support short file name. This means no name can be returned on the condition above. If it is the case, a "?" is returned as file name to indicate that the object is not accessible. To avoid this problem, configure FatFs _LFN_UNICODE = 1 and _MAX_LFN = 255 to support the full feature of LFN specification.

                        +

                        There is a problem on reading a directory of exFAT volume. The exFAT does not support short file name. This means no name can be returned on the condition above. If it is the case, "?" is returned into the fname[] to indicate that the object is not accessible. To avoid this problem, configure FatFs _LFN_UNICODE = 1 and _MAX_LFN = 255 to support the full feature of LFN specification.

                        diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/sdir.html b/firmware/chibios-portapack/ext/fatfs/doc/en/sdir.html index a01a7166..7fff827f 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/en/sdir.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/sdir.html @@ -13,7 +13,7 @@

                        DIR

                        -

                        The DIR structure is used for the work area to read a directory by f_oepndir, f_readdir, f_findfirst and f_findnext function. Application program must not modify any member in this structure, or any data on the FAT volume can be collapsed.

                        +

                        The DIR structure is used for the work area to read a directory by f_oepndir, f_readdir, f_findfirst and f_findnext function. Application program must not modify any member in this structure, or any file on the volume can be collapsed.

                         typedef struct {
                             _FDID   obj;        /* Owner file sytem object and object identifier */
                        diff --git a/firmware/chibios-portapack/ext/fatfs/doc/en/sfileinfo.html b/firmware/chibios-portapack/ext/fatfs/doc/en/sfileinfo.html
                        index 6dae1fe3..856f739d 100644
                        --- a/firmware/chibios-portapack/ext/fatfs/doc/en/sfileinfo.html
                        +++ b/firmware/chibios-portapack/ext/fatfs/doc/en/sfileinfo.html
                        @@ -13,7 +13,7 @@
                         
                         

                        FILINFO

                        -

                        The FILINFO structure holds information about the object returned by f_readdir, f_findfirst, f_findnext and f_stat function.

                        +

                        The FILINFO structure holds information about the object returned by f_readdir, f_findfirst, f_findnext and f_stat function. Be careful in the size of structure when LFN is enabled.

                         typedef struct {
                             FSIZE_t fsize;               /* File size */
                        diff --git a/firmware/chibios-portapack/ext/fatfs/doc/ja/appnote.html b/firmware/chibios-portapack/ext/fatfs/doc/ja/appnote.html
                        index af934068..d176bd70 100644
                        --- a/firmware/chibios-portapack/ext/fatfs/doc/ja/appnote.html
                        +++ b/firmware/chibios-portapack/ext/fatfs/doc/ja/appnote.html
                        @@ -64,7 +64,7 @@ FatFsモジュールはANSI C(C89)準拠で記述されているので、普通
                         

                        限界値

                          -
                        • ファイルシステム: FAT12, FAT16, FAT32(r0.0) および exFAT(r1.0)。
                        • +
                        • ファイルシステム: FAT, FAT32(r0.0) および exFAT(r1.0)。
                        • 同時オープン ファイル数: 無制限。(利用可能メモリによる)
                        • 同時マウント ボリューム数: 最大 10。
                        • ファイル サイズ: 最大 4GiB - 1 (FATボリューム) および、事実上無制限(exFATボリューム)。
                        • @@ -144,7 +144,7 @@ And any other options are left not changed from default setting.

                          長いファイル名

                          FatFsモジュールは、長いファイル名(LFN)をサポートします。ファイルに付けられた2つの異なる名前(短いファル名と長いファイル名)は、f_readdir関数を除くファイル操作関数において透過です。デフォルト構成では、LFN機能はOFFになっています。LFN機能を有効にするには、_USE_LFNを1,2または3に設定し、option/unicode.cをプロジェクトに追加します。LFN機能は、加えてある程度のワーク エリア(LFN操作バッファ)を必要とします。バッファ長は使用できるメモリに応じて_MAX_LFNで構成されることができます。LFNの長さは最大255文字に達するので、LFN完全対応のためには_MAX_LFNは255に設定されるべきです。与えられたファイル名に対してバッファ長が不足した場合、ファイル関数はFR_INVALID_NAMEで失敗します。

                          -

                          ファイル関数に再入を行う条件の下でLFN機能を使用する場合は、_USE_LFNは2または3に設定されなければなりません。この場合、ファイル関数はワーク エリアを動的に確保(スタックまたはヒープ)します。ワーク エリアのサイズは、(_MAX_LFN + 1) * 2バイト(exFAT利用時はさらに+608バイト)になるので、スタック等のサイズはそれを考慮した十分な余裕がなければなりません。

                          +

                          ファイル関数に再入を行う条件の下でLFN機能を使用する場合は、_USE_LFNは2または3に設定されなければなりません。この場合、ファイル関数はワーク エリアを動的に確保(スタックまたはヒープ)します。ワーク エリアのサイズは、(_MAX_LFN + 1) * 2バイト(exFAT利用時は加えて((_MAX_LFN + 44) / 15 * 32バイト)になるので、これらのメモリ消費量に注意を払う必要があります。

                        With LFN at CM3+gcc
                        _CODE_PAGECode size
                        @@ -165,10 +165,9 @@ And any other options are left not changed from default setting.

                        exFATファイルシステム

                        -

                        exFAT(Microsoft's Extended File Allocation Table)ファイルシステムは、既に組み込みシステムや情報家電で広く使われているFATファイルシステムを置き換える目的で開発されました。exFATは、64GiB以上のSDメモリ カードで標準ファイルシステムに採用されるなど、FATに並びリムーバブル メディアの標準ファイルシステムの一つとなりつつあります。

                        -

                        exFATボリュームでは、FATボリュームで制約となっていた4GiB以上のサイズのファイルを扱え、ファイルシステムのオーバーヘッド(特にファイル アロケーション ディレイ)も大幅に低減され、書き込みスループットがFATより向上しています。しかし、現リビジョンのFatFsでは、実装上の理由から不連続ファイルへのサイズ拡大を伴う書き込み時のとき、スループットがFATより低下します。f_expand関数による連続領域の割り当て機能は、この問題の回避に有効かもしれません。

                        -

                        exFATはマイクロソフト社が開発したものなので、マイクロソフト社はexFATについていくつかの特許を保有しています。FatFsのexFAT機能は、それの US. Pat. App. Pub. No. 2009/0164440 A1 に基づいた実装です。このため、商用製品でexFAT機能を利用する場合、製品の最終仕向地によってはライセンスが必要になります。最近のFATドライバの多くはexFAT機能を含んでいるため、それらの使用に当たってライセンスが必要になりますが、FatFsは構成オプションでexFAT機能を任意にON/OFFできるため、無効にしてライセンス問題を回避することもできます。

                        -

                        exFATを有効にすると、FatFsモジュールのC89互換は失われます(64ビット整数型が必要なため)。

                        +

                        exFAT(Microsoft's Extended File Allocation Table)ファイルシステムは、既に組み込みシステムや情報家電で広く使われているFATファイルシステムを置き換える目的で開発されました。exFATは、64GiB以上のSDメモリ カードで標準ファイルシステムに採用されるなど、FATに並びリムーバブル メディアの標準ファイルシステムの一つとなっています。exFATボリュームでは、FATボリュームで制約となっていた4GiB以上のサイズのファイルを扱え、ファイルシステムのオーバーヘッド(特にファイル アロケーション ディレイ)も大幅に低減され、書き込みスループットがFATより向上しています。

                        +

                        exFATはマイクロソフト社が開発したものなので、マイクロソフト社はexFATについていくつかの特許を保有しています。FatFsのexFAT機能は、それのUS. Pat. App. Pub. No. 2009/0164440 A1に基づいた実装です。このため、商用製品でexFAT機能を利用する場合、製品の最終仕向地によってはライセンスが必要になります。最近のFATドライバの多くはexFAT機能を含んでいるため、それらの使用に当たってライセンスが必要になりますが、FatFsは構成オプションでexFAT機能を任意にON/OFFできるため、無効にしてライセンス問題を回避することもできます。

                        +

                        exFATを有効にすると、FatFsモジュールのANSI C(C89)互換は失われます(64ビット整数型が必要なため)。

                        diff --git a/firmware/chibios-portapack/ext/fatfs/doc/ja/expand.html b/firmware/chibios-portapack/ext/fatfs/doc/ja/expand.html index 27c4e66c..8e91cf07 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/ja/expand.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/ja/expand.html @@ -30,7 +30,7 @@ FRESULT f_expand (
                        fp
                        対象となるファイル オブジェクト構造体へのポインタを指定します。
                        fsz
                        -
                        ファイルに割り当てるバイト単位のサイズ。データ型FSIZE_tは、DWORD(32-bit)またはQWORD(64-bit)のエリアスで、exFATサポートの有無により切り替わります。
                        +
                        ファイルに割り当てるバイト単位のサイズ。データ型FSIZE_tは、DWORD(32ビット)またはQWORD(64ビット)のエリアスで、exFATサポートの有無により切り替わります。
                        opt
                        実際に割り当てを行うかどうか指定するフラグ。
                        @@ -79,15 +79,15 @@ FRESULT f_expand ( res = f_open(fp = malloc(sizeof (FIL)), "file.dat", FA_WRITE|FA_CREATE_ALWAYS); if (res) { /* ファイルが開かれたかチェック */ free(fp); - ... + die("Failed to open the file."); } /* 100 MiB の連続領域を割り当てる */ res = f_expand(fp, 104857600, 1); if (res) { /* 割り当てられたかチェック */ - ... + f_close(fp); free(fp); - ... + die("Failed to allocate contiguous area."); } /* 連続ファイル作成成功 fp でアクセス可能 */ diff --git a/firmware/chibios-portapack/ext/fatfs/doc/ja/fdisk.html b/firmware/chibios-portapack/ext/fatfs/doc/ja/fdisk.html index 82fc6c24..3e3b0840 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/ja/fdisk.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/ja/fdisk.html @@ -62,15 +62,14 @@ FRESULT f_fdisk ( /* ユーザ定義のボリューム管理テーブル (_MULTI_PARTITION == 1 のとき必要) */ PARTITION VolToPart[] = { - {0, 1}, /* 論理ドライブ 0 ==> 物理ドライブ 0, 第1区画 */ - {0, 2}, /* 論理ドライブ 1 ==> 物理ドライブ 0, 第2区画 */ - {1, 0} /* 論理ドライブ 2 ==> 物理ドライブ 1, 自動検出 */ + {0, 1}, /* "0:" ==> 物理ドライブ 0, 第1区画 */ + {0, 2}, /* "1:" ==> 物理ドライブ 0, 第2区画 */ + {1, 0} /* "2:" ==> 物理ドライブ 1, 自動検出 */ };
                             /* 新しい物理ドライブ(0)の初期化 */
                         
                        -    FATFS fs;
                             DWORD plist[] = {50, 50, 0, 0};  /* 第1区画,第2区画それぞれに50%ずつ割り当て */
                             BYTE work[_MAX_SS];
                         
                        diff --git a/firmware/chibios-portapack/ext/fatfs/doc/ja/lseek.html b/firmware/chibios-portapack/ext/fatfs/doc/ja/lseek.html
                        index 00e4a958..45781871 100644
                        --- a/firmware/chibios-portapack/ext/fatfs/doc/ja/lseek.html
                        +++ b/firmware/chibios-portapack/ext/fatfs/doc/ja/lseek.html
                        @@ -28,7 +28,7 @@ FRESULT f_lseek (
                         
                        fp
                        対象となるファイル オブジェクト構造体へのポインタを指定します。
                        ofs
                        -
                        移動先のオフセット(リード/ライト ポインタ)値。ファイル先頭からのオフセットをバイト単位で指定します。データ型FSIZE_tは、DWORD(32-bit)またはQWORD(64-bit)のエリアスで、exFATサポートの有無により切り替わります。
                        +
                        移動先のオフセット(リード/ライト ポインタ)値。ファイル先頭からのオフセットをバイト単位で指定します。データ型FSIZE_tは、DWORD(32ビット)またはQWORD(64ビット)のエリアスで、exFATサポートの有無により切り替わります。
                        @@ -48,7 +48,8 @@ FRESULT f_lseek (

                        解説

                        -

                        ファイルのリード/ライト ポインタ(次に読み出し・書き込みされるバイトのオフセット)を移動します。オフセットの原点はファイル先頭です。書き込みモードでファイル サイズより大きな値を指定すると、そこまでファイル サイズが拡張され、拡張された部分のデータは未定義となります。データを遅延無く高速に書き込みたいときは、予めこの関数で必要なサイズまでファイル サイズを拡張しておくと良いでしょう。ファイルに連続したデータ領域を割り当てる必要があるときは、f_expand関数を使用してください。f_lseek関数が正常終了したあとは、リード/ライト ポインタが正しく移動したかチェックするべきです。リード/ライト ポインタが指定より小さいときは、次の原因が考えられます。

                        +

                        各ファイル オブジェクトが持つリード/ライト ポインタは、次に読み出し・書き込みされるバイトのオフセットを保持し、読み書きされただけ進みます。この関数は、ファイルへの読み書きを行わずにリード/ライト ポインタのみ移動します。

                        +

                        書き込みモードでファイル サイズより大きな値を指定すると、そこまでファイル サイズが拡張されますが、拡張された部分のデータは未定義となります。データを遅延無く高速に書き込みたいときは、予めこの関数で必要なサイズまでファイル サイズを拡張しておくと良いでしょう。ファイルに連続したデータ領域を割り当てる必要があるときは、f_expand関数を使用してください。f_lseek関数が正常終了したあとは、リード/ライト ポインタが正しく移動したかチェックするべきです。リード/ライト ポインタが指定より小さいときは、次の原因が考えられます。

                        • 非書き込みモードまたは高速シーク モードのため、ファイル サイズでクリップされた。
                        • ファイル拡張中にディスクが満杯になった。
                        • diff --git a/firmware/chibios-portapack/ext/fatfs/doc/ja/rc.html b/firmware/chibios-portapack/ext/fatfs/doc/ja/rc.html index 50005e8a..59b48718 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/ja/rc.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/ja/rc.html @@ -27,7 +27,14 @@
                        ※開かれたファイルの操作においてこのエラーが発生すると、そのファイル オブジェクトはアボート状態となり、クローズ以外の操作ができなくなります。
                        FR_NOT_READY
                        -
                        下位レイヤ(disk_initialize関数)の失敗。つまり、物理ドライブが動作可能な状態にない。
                        +
                        下位レイヤ(disk_initialize関数)の失敗。次のような理由が考えられる。 +
                          +
                        • ドライブにメディアがセットされていない。
                        • +
                        • 下位レイヤの実装が不完全。
                        • +
                        • 間違ったハードウェア構成。
                        • +
                        • ストレージ デバイスの故障。
                        • +
                        +
                        FR_NO_FILE
                        指定されたファイルが見つからなかった。
                        FR_NO_PATH
                        @@ -51,9 +58,9 @@
                        FR_INVALID_OBJECT
                        指定されたファイル オブジェクトやディレクトリ オブジェクトが無効、またはヌル ポインタが渡された。無効になる理由は次のことが考えられます。
                          -
                        • オープンされていない、既に閉じられた、破損しているなど。
                        • +
                        • オープンされていない、既に閉じられている、破損しているなど。
                        • そのボリュームでマウント動作があり、ボリューム上の開かれたオブジェクトが全て無効化された。
                        • -
                        • 物理ドライブがメディアの取り外しで動作不可能になっている。
                        • +
                        • 物理ドライブがメディアの取り外し等で動作不可能になっている。
                        FR_WRITE_PROTECTED
                        diff --git a/firmware/chibios-portapack/ext/fatfs/doc/ja/sfileinfo.html b/firmware/chibios-portapack/ext/fatfs/doc/ja/sfileinfo.html index f6694109..ea063202 100644 --- a/firmware/chibios-portapack/ext/fatfs/doc/ja/sfileinfo.html +++ b/firmware/chibios-portapack/ext/fatfs/doc/ja/sfileinfo.html @@ -13,7 +13,7 @@

                        FILINFO

                        -

                        FILINFO構造体は、f_stat/f_readdir/f_findfirst/f_findnext関数で返されるオブジェクトに関する情報を保持します。

                        +

                        FILINFO構造体は、f_stat/f_readdir/f_findfirst/f_findnext関数で返されるオブジェクトに関する情報を保持します。LFN使用時はサイズが大きく増加するので注意が必要です。

                         typedef struct {
                             FSIZE_t fsize;               /* ファイル サイズ */
                        diff --git a/firmware/chibios-portapack/ext/fatfs/doc/res/app4.c b/firmware/chibios-portapack/ext/fatfs/doc/res/app4.c
                        index 03d124de..56c07fec 100644
                        --- a/firmware/chibios-portapack/ext/fatfs/doc/res/app4.c
                        +++ b/firmware/chibios-portapack/ext/fatfs/doc/res/app4.c
                        @@ -1,5 +1,5 @@
                         /*----------------------------------------------------------------------/
                        -/ Low level disk I/O module function checker
                        +/ Low level disk I/O module function checker                            /
                         /-----------------------------------------------------------------------/
                         / WARNING: The data on the target drive will be lost!
                         */
                        @@ -41,8 +41,8 @@ int test_diskio (
                         )
                         {
                             UINT n, cc, ns;
                        -    DWORD sz_drv, lba, lba2, pns = 1;
                        -    WORD sz_sect, sz_eblk;
                        +    DWORD sz_drv, lba, lba2, sz_eblk, pns = 1;
                        +    WORD sz_sect;
                             BYTE *pbuff = (BYTE*)buff;
                             DSTATUS ds;
                             DRESULT dr;
                        @@ -113,7 +113,7 @@ int test_diskio (
                                     printf(" - failed.\n");
                                 }
                                 if (dr == RES_OK || sz_eblk >= 2) {
                        -            printf(" Size of the erase block is %u sectors.\n", sz_eblk);
                        +            printf(" Size of the erase block is %lu sectors.\n", sz_eblk);
                                 } else {
                                     printf(" Size of the erase block is unknown.\n");
                                 }
                        @@ -196,7 +196,7 @@ int test_diskio (
                                 pns++;
                         
                                 /* Single sector write test (misaligned memory address) */
                        -        printf("**** Single sector write test 2 ****\n");
                        +        printf("**** Single sector write test (misaligned address) ****\n");
                                 lba = 5;
                                 for (n = 0, pn(pns); n < sz_sect; n++) pbuff[n+3] = (BYTE)pn(0);
                                 printf(" disk_write(%u, 0x%X, %lu, 1)", pdrv, (UINT)(pbuff+3), lba);
                        diff --git a/firmware/chibios-portapack/ext/fatfs/doc/res/layers3.png b/firmware/chibios-portapack/ext/fatfs/doc/res/layers3.png
                        deleted file mode 100644
                        index ac439b0b1e32b14ed3ce4a32a54340a9431e863a..0000000000000000000000000000000000000000
                        GIT binary patch
                        literal 0
                        HcmV?d00001
                        
                        literal 2379
                        zcmV-R3AFZ!P)009340{{R3+XRg;0000mP)t-s00000
                        zO-)TrO#p*}XlQ7FfPetO!J3+yqobn$|NqFy$lBW4=;-MG|BUnV^Z)<<^C83T00009
                        za7bBm00000000000qSKIqyPX2!AV3xRCt{2+)azyMi>C#Nxg2q*lbRP-u4)B$wHy9
                        zx4q|(z4Vkq5_;PIP{>{igDk8q3k!QQIf+e(_Gog5b1603g8c^;dNkXEOi785jHdIB
                        zB-@hpF(YZl=|(E4_2JCpcV;Bbj5I-)Yg@*su^YRw8@sXBXOB_!rL;{dFVn_u?8Yv#
                        zv9Uf+gECtf$*EOSmp3zSiV~g2C*omRMV>pxa4FAa*)FxUl)9!FF0F1s
                        zU6W-)4&#(_%+hD36`o_#%A15gfa4<8*frYam&R`FDD`;PMWKz*R`eZ&HdWdP#lN+x
                        zOS94H_ma3Id%Q|R=ql{-R{B?wd^?Ly;4~rP^uLZ0XyZ678ZCrxNYl
                        z9EW97nq8dWRGM8F_9F1QZJzX|l5CE!=Yd}%n=iTPwXrhJ>6
                        zza-~qK+s)Jy*=F`hx-OW58Z9)c04s^Z~yg(pdbF--&*}Ea_!zr@8+kw1ofu9G`rU4
                        z1_>LriF3!jMbLTgJjJeWNwK{)`FM|P5H#JJs-jQ$f-Ad-?cVpLKi`~brk1f`2fxnH=je{s96r@K_+bHS9
                        zsvH}A9i+2M?c-(eSkM+~rv|Z}+z67n9Y)Spf?#$a4Ts*#=w9EAfOa
                        z&<_pl)&cy0Zx=QzJccG2nmR%q{_`*b5*6^NUAoM~>K?0j>2a-Z5SBKx>?bnv1j
                        zc#h@biSf0}B)OLqn{!-Ij?FioD$C{>N0w%DjGs%i3!fWEwey$8ZtUx0Xa6JxcFI*n
                        znVlK93Og%s6?PV`#LhS(-DbCw^uX2F>9`_0^_X-!JM1sOUQ@eebG$ZtyiPmF_4S-%
                        z>$Nj8U6q{{xQaGY)>)>^PU{oZ`rIHV(}i1-B1@5-*=&<)XI)p7%&W<`kE(fZ52fO2
                        z>?n8RWv=LbMU;jsvd4+aq0*iQz8t$MJAOVbp1mjELQc-?z~SCtfAoJ}BQsO8dEZY>
                        z!7JDu(#N>N{ch~IlD&M?F=o22*}iFWzn7bBUum}6h4fhJbc@F2bzy}apPfx;+`ied
                        z9m9PK-|@QiFqsVa-w7UP*gnQxPxm^r4$DuvMNHyYYz2-_Foro0Y%&Oqm43(VLJrVB
                        z{O===(`~ooX@1AmAQng$N^>+EuoXCN4*D?n1CDmOVd)FoiEB(`2eUaQ{YfyN2Bz>#
                        zEYoHya2(r^=N^7T930patAri9p~mcff6^a>Hm0Sm5w^l?0yg=>95~wRz#e!yAwz-k
                        zUW$Gt&&fn{aafkD3UmouS>$<;*M0V#{>axxBK3SV3kaLi6VxvD1H!u2fe9vrt;Fiu
                        z03v3#Ep~oq+w5fWbg1T#{}&ofAMzho*m)3~V|_Tsg8FFEodVaj47=je*p1!TjosMm
                        zvJ>}j-|}cX4CA+u65KiAraghXX>ePAhu=HFQ3o1O^ay-9n6~h2Av>kbd*!ULz|NjuhU_6AMT*cc61WW4|T8&
                        zt(yUSLJQs3x$RijU}5*|K5GfHmbXh=O5m8#atq?7+0D8F5Vr-bItxDG5Zfu*A4{~?
                        zu2}1Y*^Xs0TXT)j_D$MY3CmmWVmJby;XGxrK5$w)^$HI{dqNAJ?(sWbH>zv2M-Y{_
                        zafaate2UmBBP(;;gfch6@}_MtXeD{9DMo1U8vI)XQF$8^3`gLT6@$iQuMX-gmA7e6
                        z22jtTj?q=HX{UgK(1LT>D%*tCVsOM|^_;J~WAyTV$Y%R*{F*?C;-C`%W#9E7Sn^IA
                        z_4!oqcarw{a8M%T3{t@rVi?YvD`
                        zxUOrdF-LaACD-1}c|a!LPS0-@Hp(15S72v9CX#OFjh!p8v!1=Hu+wQpd7k@ty3$f?
                        z%Y0r@V9Ta+oG+XYR28EvTf+_i#=HwO!-u_{EDg3Ph^Pr0ZkK6levG@@@^tnUL2uEU4K=p6k1T3$k!`X;yk8Ir{!?NTZ|@Pa
                        zp@Y!-S*;B@9>h%uA`0xqIkq?G8O%PUrM!KSw56WkzoQ4lZByGpKay7ul-dQ01Y6p@
                        zM6DfbG_`r``q~b$C_a0;zP4fsyQVgBDZ8e=K{>mgK2bTlp1xp7yOut1NxPQ5e_6YZ
                        zF^|%A4P!m!?doG(73|7mdsXbJW15xhietGI?Mh?VmF>&&WA}B~WtT747H_ZBXN$K}
                        x8~gujue^3s^z|BT!KJYqyRjR)u^YRx{U2)j?V=PCmQ?@%002ovPDHLkV1kIi%c}qY
                        
                        diff --git a/firmware/chibios-portapack/ext/fatfs/doc/res/mkfatimg.zip b/firmware/chibios-portapack/ext/fatfs/doc/res/mkfatimg.zip
                        index d0728b4ead1a7111d8dd79f8a3c2bf5313fb5e25..67d423b166931db64a39479824671db19b7486ce 100644
                        GIT binary patch
                        delta 2728
                        zcmZ{m`9IT-AHcUcw<2dMXNr+4H#0?UQ_K}Unw;fa)UX`ykQzmfX1R|f1KEdbAMSm4
                        z_Tk-!Zy)|Qdo*bK8-R;j3Wa-NO!zSgr3~2Dr$!ME>
                        zaUs6=)t~Kd%-6ZPw`KVKCjvC9b9bz#nhzYQRBgat>Qw_c2WRXZAx$$o=7=Sj8tKvz
                        zt495})T=jQ=CMUsdx`X0lqWMrZCcOmnggsJe_u)b^SyT7Rk3Lh{O+Di;DCBy2h^&*
                        zNMo#VSkl|BF1sE5OBOx~^<6~Lx
                        zlzwlB4+_ECR?c}(rW+?MPiAmtug&ot$wUKHH;#00d1tHC6}vOpZ8tPUh431XC3)AV
                        z7FUr0L5wxo;RWSn!`{nBI)q$Rsc)m2(bP6MsJI|tuXohhXZW89`w^(Dj5#u*=6mat
                        zLerPrHEjKzoIyEOGg*opo3i2dsdd&Z9G;jmW6*wgI`rcF(9gzA%@DJf*d7nUOJ2zq
                        z0SBeq2DhT+OGe-Fw#%Z(!VXn@vvR|aWvNad9DDC3vpaPZckDk|ycCboBY$nh==QZO
                        ziBrpf`pNSah|PZ}jK(0k9CdASw24OFuKc=KXIV2%hDyT=DR5V7kvFc$2BX>mHmY17
                        zZz~b8EOCHAGkU%oo0YryZBd|$E{OvMnzhXh&4%R>;ip&VNYna!+u9GRFJw#5NNj%Q%Egk+%!w-a}
                        z`IVfA-TbDPa85%>BGTyaTqM7N=>>P@A+POKn9nh&viS_-s?NjIsEJLH#R+u-K%Cd4
                        zHxKGc%={8FAA8bte2h#fUkSL6)WURFE5vZq)+-IA)|(_o?<}ILhOu6P*zL1ljJkV-
                        zdcm?MH6X#dHny5eX~y}I?vz=SKjSvd`1|P;3L^elhjfn&I_?#{dsl&|0!}CR^jh8G
                        z#YU!{#cs5@CT)qOFICJ_Ii}gYXKd#irK0If4XsPb^kB{hBU@`Aua|O8mgh%fY1%{~nxmZ0b(yV@24IcPK+wukNJt<}H
                        zERlCUzXqlXX&66B_JxuVp0ycIn8RQI-PxPt`o5lEf%2qeaG3O;2IW)11!zQs_dt8Sxy^RST9aT>Yu($#_aE9EY-RIFYX?%H>WdJ%%jV
                        zq|v*xCO7roEKKnMtf`<@3Oo2$Nk9x%gRrC%&=iVscvWLup!ujLTGx=qjkZ1ogk2>A9JfIBKAQ|GxAdW7~#dWJ4YXB_}mdaWBjCM
                        z;$pp#)6VNypxKIQ^KhYWr(CMI-Qmu0a*u~O;lcrLx^%d8jn|lcv1w5Cl>hZJ1?_Ti
                        z5S6S#JsB_NF)yO)6a`Zpk@O5n+BkL0EAzc&WF9ruO=#NmYVwf%;9|gb7jRQTB{jm(
                        zMwc~ye_`{ew(n&iRIOq~`E_iCtHPmXgrII*2EW!CFhi|YT3BF@uH8&_;Wj~-PUh-8
                        znx1IY*2;3Yjd*DPNtu&%BjgLsg+s}h-`}_%Z+mmx7t}qGBHpGdai#JJa2?tTxNI<
                        zjRyoVN3ivh9}zu^>f_}TmX9~_>XjWh-c_LS1r!b6ION4z|8rMhD8=toKgIUd6mL-?
                        z-R=WBCTlLnk(4pPnpW_(*v{n3}AjLCMj392E4-BQO$Po89_&jHT
                        zL2$B0Ug}~|I7EzyBW~b+ZE)~GskkAKaH}F$fx)zy$4gtW^qEHaljwMxx+A1qkLAdj
                        z1LOQNFT}IX<*X0n9M=z<3i%b3{+SSv@u|v6{bOGDj|S+oTAX<;rioT{kYxxMviX~C
                        z3wau&wl7{?N1`Y#)fqhBwxwv~qVxUZwNC}3)Nu9qIcoxaOjSs&p8Im(kLft&AjYo*
                        zy8m02jr?ee-2_B=x^N`oS@uwb^sk#fj!pUEWiN2~*;IDcd*y!Z%3b%WiFdIKg8J{d
                        zpJmtTj~~1=pM7ruUS=)ee6|WePNp)@7$K+d0-{2B*=ggUlW;al@>biU@h`+uWkz3p^wQt
                        zX$UqL
                        
                        delta 2688
                        zcmV-`3V-$6^eM*lDX@C9f0ClpL@?lQJYfj{0QDLG00sa60BvDuZZ2b;S#5LTMiTyv
                        ztNb6@T&*Kvz<^)wV(d*}0|^xyyMWE!mgAxX8X3hPQIasR@A&WO?wQdG2Cox#mqIhs
                        zuk*~)J=()U=^uU$cXti}+KmCYGwV^nI1pCk2hgjOD^C*Y>j
                        z9b!z?)7)|8Kc`=EhXuHCJ$JU4fw!2AL;$`6s3MF+5Q2m8@@gQ@l#ZOzaa7Blo}AP^
                        zs^q8!Dm>-N<=y45f4i9BRG7=<&?C~*jpZrxV}I_75R9ssc7P>&z8|%`=*o*w_TOu=
                        z0ZxML24ajm_5#9-0@9iVR%Z?iY&C
                        z{CeAKnst)y3Cjk{lX#EB42-rFwL_S=wkOsqCf~Ro_*IgcX$4`yOUFXP7tWL
                        zI7jQksql(m^LOwJ7f_)YnZgmTVl$(q(w-v$Toy(FfBrC3046Q8Gczg}o(bmx+H#D2
                        z9WN=tfb)liJTD-RP_&Kg)5d@}y;^q>_S?28cl~ybCX!=D8$)$vOu&T#gG>f;?&_OGa139v;NxgG-4
                        zf3s8kdAko|C79g_M4zyp>Pl>tvcIRXZJ=qne~RoQHxnUD#3r+JOb!l|HmOYS^V{4x
                        z=vgeP{rwc8TSZ6%Uio9FbB_R)Imn{-=T^7X>s$?ctwys575;mB*Xj;i|Lyb#o$k+a
                        z5M$X6;28U%zX--6>)|$Nr`B#r=_(1p8Pa;jD7hXJ5#qBkyh6VbZH?=%jcB-MUn8cH
                        zikU^AGh7A;kyMtX0)zO`BrW@+rPi~8<%E1ux{`^jsUM18EYD8d(o@cGOp~#JG{jI1
                        z9#H(=V`cGie4AT#@;m9|YN1cVDrTKMf1=+mR&GujQL3cg*c{h~YDOhX^A`zobSx>E
                        z6#r$IGA=J^GSq{Ch!)r~1kd=e%9b)L)du~tg2!=@D`$azKi@y7!p1df9KP0*BDb6*
                        zg={&(U4MP{r@HD{E=5v=C|G!7i5=y|*!RLn7UzP$h#XnZx$+?ZJJ>L|)|6U_f4LPP
                        zL2|ztmm%^GK3_nMcB{Z1TJ8fO;D^!=Dvg|JMYVbb(rhV8Xg1?jRVLbU^@fp=Qi*@3
                        zOBIjnC^+@2v{&bFv{ncgAzm`hVD^L!nmc=h`%?6Pt-d^6o^OlKaE=+6FCvB$K0PO`
                        z;%B%&SN*npen7NIl;r7tQi{%Ce;~sU*k&z4M5l$Y;f^?<*3b8*FCaCRv$7c<&Y+(>
                        zt*uLYcgBsR@=)HNXnai~9l=@L5+d=>{lE&eKeDS$^@qQ@mureLu_v1Ja7uRcf*CNd
                        zkG2-m=nPvsQ>&5(T*1Do4-7$L{*sgrg^`1U2VSo*i5s0v(0HodrMbv=e~pwR6rjfF
                        z4qtIL#_5R(KfPUh2Iys7LtgQ_>eN+&81dK#_zN#G_PIqy4CghI>Mp?v4I0FQhK9|p
                        zjhLzjiT*M)>_0G*nf*ZEq_ZCPYdV89l|kh;m5QVh;8xi8)OBG!k~dw2QhB6<*<;GY
                        z06=@+^<}leohFS6vPlm^f7Bam0p3_5Ak6-Cb4a9Qs2ziY%tbKH-yW|wAtlz_DtA;f
                        z<%W@DLLVyQk_7QiS_BWj>&aO7O7-y7nHNFW4u8!v(>6`pJZ2|%xE!v4p%G8@mQshRRe}cnI$?r;?f1Jw;
                        zT-h6v0=oFn@WDY`)W|WF(tEiS7mX~W)dHOZOf#t|z)=m4M#{p0W@cGHF-vr^JT-+U
                        z>kz7^bv-wy+fCMy)B^t!nCm{lq1SFIguxF6j?80Y7=I!caqd>JTK&#TLAg
                        zFVS97?!!qw!?z94K{T
                        z%9=b6)!LbYjT1u(@rQUJG|K0FsG9h2QmqouBwwRQ(wU|8f1Pg9SKA;?A@Otxr_YmD
                        zcX3FSbu+rIZ7^{BVFN?}+YGGYo{3hh6NT+MjtEGUUq&rPC8id<#d$*5!v1@OB$uXr
                        zwPnbSTRB_3f}=B{86@?Jk;}5Ca%XNrqH7b8tJiDqDnojX&pW~{CIm;%lKwTCy-3sS
                        zPitg>wLU{Hf2?O4bvT=;!`Vn3PL?`i;xIT1L<((Rd;3Z;_U@S5!Ow_ff);&x^qJ}r20$aNAQbQeY48TPLhjnOqF)c*^T
                        zT+7s}4&|bH&m2P|xvvvrul@pqaI}YTv;l{3v;v24v;&85v;>E6v;~K7v<8Q8v<}~8UO$W000000000103ZOifpD|{0BvDu
                        zZZ2b&5qAnI0`vsw`0F%lz0j{0!S{G(0B?u0N*W!FdWi
                        uDi?JM0B>+~X>V>Xb#7^6Z)9aIV^B*41^@s602BZe0C5BW0Kat#0000c?G#!7
                        
                        diff --git a/firmware/chibios-portapack/ext/fatfs/doc/res/mkfs.xls b/firmware/chibios-portapack/ext/fatfs/doc/res/mkfs.xls
                        index f01ddcc8ce572a781312620d03d47549f3487d7c..3c615cb7b78badecaa2947865a299de638e7b037 100644
                        GIT binary patch
                        delta 123
                        zcmWl|Np3*_007W@Ln&&inVM%U{={C1n*=HFXV5EkD{ix_bHshDOFFre@|Ae*IZmS^tOIP2zmJ
                        NK2FESWw!|r!3*&hD>DE9
                        
                        delta 123
                        zcmWl|w~0al002!e~9OYi~VxhdKJ
                        
                        diff --git a/firmware/chibios-portapack/ext/fatfs/doc/updates.txt b/firmware/chibios-portapack/ext/fatfs/doc/updates.txt
                        index ebb6026a..d4965f90 100644
                        --- a/firmware/chibios-portapack/ext/fatfs/doc/updates.txt
                        +++ b/firmware/chibios-portapack/ext/fatfs/doc/updates.txt
                        @@ -1,5 +1,11 @@
                        +R0.12c (March 04, 2017)
                        +  Improved write throughput at the fragmented file on the exFAT volume.
                        +  Made memory usage for exFAT be able to be reduced as decreasing _MAX_LFN.
                        +  Fixed successive f_getfree() can return wrong count on the FAT12/16 volume. (appeared at R0.12)
                        +  Fixed configuration option _VOLUMES cannot be set 10. (appeared at R0.10c)
                        +
                         R0.12b (September 4, 2016)
                        -  Improved f_rename() to be able to rename objects with the same name but case.
                        +  Make f_rename() be able to rename objects with the same name but case.
                           Fixed an error in the case conversion teble of code page 866. (ff.c)
                           Fixed writing data is truncated at the file offset 4GiB on the exFAT volume. (appeared at R0.12)
                           Fixed creating a file in the root directory of exFAT volume can fail. (appeared at R0.12)
                        diff --git a/firmware/chibios-portapack/ext/fatfs/src/00history.txt b/firmware/chibios-portapack/ext/fatfs/src/00history.txt
                        index 49aac282..fa736381 100644
                        --- a/firmware/chibios-portapack/ext/fatfs/src/00history.txt
                        +++ b/firmware/chibios-portapack/ext/fatfs/src/00history.txt
                        @@ -212,7 +212,7 @@ R0.10a (January 15, 2014)
                         R0.10b (May 19, 2014)
                         
                           Fixed a hard error in the disk I/O layer can collapse the directory entry.
                        -  Fixed LFN entry is not deleted on delete/rename an object with lossy converted SFN. (appeared at R0.07)
                        +  Fixed LFN entry is not deleted when delete/rename an object with lossy converted SFN. (appeared at R0.07)
                         
                         
                         
                        @@ -268,7 +268,7 @@ R0.12a (July 10, 2016)
                         
                         R0.12b (September 04, 2016)
                         
                        -  Improved f_rename() to be able to rename objects with the same name but case.
                        +  Made f_rename() be able to rename objects with the same name but case.
                           Fixed an error in the case conversion teble of code page 866. (ff.c)
                           Fixed writing data is truncated at the file offset 4GiB on the exFAT volume. (appeared at R0.12)
                           Fixed creating a file in the root directory of exFAT volume can fail. (appeared at R0.12)
                        @@ -277,3 +277,12 @@ R0.12b (September 04, 2016)
                           Fixed large file allocation/removing on the exFAT volume collapses allocation bitmap. (appeared at R0.12)
                           Fixed some internal errors in f_expand() and f_lseek(). (appeared at R0.12)
                         
                        +
                        +
                        +R0.12c (March 04, 2017)
                        +
                        +  Improved write throughput at the fragmented file on the exFAT volume.
                        +  Made memory usage for exFAT be able to be reduced as decreasing _MAX_LFN.
                        +  Fixed successive f_getfree() can return wrong count on the FAT12/16 volume. (appeared at R0.12)
                        +  Fixed configuration option _VOLUMES cannot be set 10. (appeared at R0.10c)
                        +
                        diff --git a/firmware/chibios-portapack/ext/fatfs/src/00readme.txt b/firmware/chibios-portapack/ext/fatfs/src/00readme.txt
                        index 42426a40..2b7cc760 100644
                        --- a/firmware/chibios-portapack/ext/fatfs/src/00readme.txt
                        +++ b/firmware/chibios-portapack/ext/fatfs/src/00readme.txt
                        @@ -1,21 +1,21 @@
                        -FatFs Module Source Files R0.12a
                        +FatFs Module Source Files R0.12c
                         
                         
                         FILES
                         
                        -  00readme.txt This file.
                        -  history.txt  Revision history.
                        -  ffconf.h     Configuration file for FatFs module.
                        -  ff.h         Common include file for FatFs and application module.
                        -  ff.c         FatFs module.
                        -  diskio.h     Common include file for FatFs and disk I/O module.
                        -  diskio.c     An example of glue function to attach existing disk I/O module to FatFs.
                        -  integer.h    Integer type definitions for FatFs.
                        -  option       Optional external functions.
                        +  00readme.txt   This file.
                        +  00history.txt  Revision history.
                        +  ff.c           FatFs module.
                        +  ffconf.h       Configuration file of FatFs module.
                        +  ff.h           Common include file for FatFs and application module.
                        +  diskio.h       Common include file for FatFs and disk I/O module.
                        +  diskio.c       An example of glue function to attach existing disk I/O module to FatFs.
                        +  integer.h      Integer type definitions for FatFs.
                        +  option         Optional external modules.
                         
                         
                           Low level disk I/O module is not included in this archive because the FatFs
                        -  module is only a generic file system layer and not depend on any specific
                        -  storage device. You have to provide a low level disk I/O module that written
                        -  to control the target storage device.
                        +  module is only a generic file system layer and it does not depend on any specific
                        +  storage device. You have to provide a low level disk I/O module written to
                        +  control the storage device that attached to the target system.
                         
                        diff --git a/firmware/chibios-portapack/ext/fatfs/src/ff.c b/firmware/chibios-portapack/ext/fatfs/src/ff.c
                        index ffc52409..faac347b 100644
                        --- a/firmware/chibios-portapack/ext/fatfs/src/ff.c
                        +++ b/firmware/chibios-portapack/ext/fatfs/src/ff.c
                        @@ -1,13 +1,13 @@
                         /*----------------------------------------------------------------------------/
                        -/  FatFs - Generic FAT file system module  R0.12b                             /
                        +/  FatFs - Generic FAT file system module  R0.12c                             /
                         /-----------------------------------------------------------------------------/
                         /
                        -/ Copyright (C) 2016, ChaN, all right reserved.
                        +/ Copyright (C) 2017, ChaN, all right reserved.
                         /
                         / FatFs module is an open source software. Redistribution and use of FatFs in
                         / source and binary forms, with or without modification, are permitted provided
                         / that the following condition is met:
                        -
                        +/
                         / 1. Redistributions of source code must retain the above copyright notice,
                         /    this condition and the following disclaimer.
                         /
                        @@ -28,65 +28,11 @@
                         
                         ---------------------------------------------------------------------------*/
                         
                        -#if _FATFS != 68020	/* Revision ID */
                        +#if _FATFS != 68300	/* Revision ID */
                         #error Wrong include file (ff.h).
                         #endif
                         
                         
                        -#define	ABORT(fs, res)		{ fp->err = (BYTE)(res); LEAVE_FF(fs, res); }
                        -
                        -
                        -/* Reentrancy related */
                        -#if _FS_REENTRANT
                        -#if _USE_LFN == 1
                        -#error Static LFN work area cannot be used at thread-safe configuration
                        -#endif
                        -#define	ENTER_FF(fs)		{ if (!lock_fs(fs)) return FR_TIMEOUT; }
                        -#define	LEAVE_FF(fs, res)	{ unlock_fs(fs, res); return res; }
                        -#else
                        -#define	ENTER_FF(fs)
                        -#define LEAVE_FF(fs, res)	return res
                        -#endif
                        -
                        -
                        -
                        -/* Definitions of sector size */
                        -#if (_MAX_SS < _MIN_SS) || (_MAX_SS != 512 && _MAX_SS != 1024 && _MAX_SS != 2048 && _MAX_SS != 4096) || (_MIN_SS != 512 && _MIN_SS != 1024 && _MIN_SS != 2048 && _MIN_SS != 4096)
                        -#error Wrong sector size configuration
                        -#endif
                        -#if _MAX_SS == _MIN_SS
                        -#define	SS(fs)	((UINT)_MAX_SS)	/* Fixed sector size */
                        -#else
                        -#define	SS(fs)	((fs)->ssize)	/* Variable sector size */
                        -#endif
                        -
                        -
                        -/* Timestamp */
                        -#if _FS_NORTC == 1
                        -#if _NORTC_YEAR < 1980 || _NORTC_YEAR > 2107 || _NORTC_MON < 1 || _NORTC_MON > 12 || _NORTC_MDAY < 1 || _NORTC_MDAY > 31
                        -#error Invalid _FS_NORTC settings
                        -#endif
                        -#define GET_FATTIME()	((DWORD)(_NORTC_YEAR - 1980) << 25 | (DWORD)_NORTC_MON << 21 | (DWORD)_NORTC_MDAY << 16)
                        -#else
                        -#define GET_FATTIME()	get_fattime()
                        -#endif
                        -
                        -
                        -/* File lock controls */
                        -#if _FS_LOCK != 0
                        -#if _FS_READONLY
                        -#error _FS_LOCK must be 0 at read-only configuration
                        -#endif
                        -typedef struct {
                        -	FATFS *fs;		/* Object ID 1, volume (NULL:blank entry) */
                        -	DWORD clu;		/* Object ID 2, directory (0:root) */
                        -	DWORD ofs;		/* Object ID 3, directory offset */
                        -	WORD ctr;		/* Object open counter, 0:none, 0x01..0xFF:read mode open count, 0x100:write mode */
                        -} FILESEM;
                        -#endif
                        -
                        -
                        -
                         /* DBCS code ranges and SBCS upper conversion tables */
                         
                         #if _CODE_PAGE == 932	/* Japanese Shift-JIS */
                        @@ -351,20 +297,20 @@ typedef struct {
                         #endif /* _DF1S */
                         
                         
                        -/* File attribute bits (internal use) */
                        +/* Additional file attribute bits for internal use */
                         #define	AM_VOL		0x08	/* Volume label */
                         #define AM_LFN		0x0F	/* LFN entry */
                         #define AM_MASK		0x3F	/* Mask of defined bits */
                         
                         
                        -/* File access control and file status flags (internal use) */
                        +/* Additional file access control and file status flags for internal use */
                         #define FA_SEEKEND	0x20	/* Seek to end of the file on file open */
                         #define FA_MODIFIED	0x40	/* File has been modified */
                         #define FA_DIRTY	0x80	/* FIL.buf[] needs to be written-back */
                         
                         
                        -/* Name status flags */
                        -#define NSFLAG		11		/* Index of name status byte in fn[] */
                        +/* Name status flags in fn[] */
                        +#define NSFLAG		11		/* Index of the name status byte */
                         #define NS_LOSS		0x01	/* Out of 8.3 format */
                         #define NS_LFN		0x02	/* Force to create LFN entry */
                         #define NS_LAST		0x04	/* Last segment */
                        @@ -375,18 +321,17 @@ typedef struct {
                         #define NS_NONAME	0x80	/* Not followed */
                         
                         
                        -/* Limits and boundaries (differ from specs but correct for real DOS/Windows) */
                        -#define MAX_FAT12	0xFF5			/* Maximum number of FAT12 clusters */
                        -#define	MAX_FAT16	0xFFF5			/* Maximum number of FAT16 clusters */
                        -#define	MAX_FAT32	0xFFFFFF5		/* Maximum number of FAT32 clusters */
                        -#define	MAX_EXFAT	0x7FFFFFFD		/* Maximum number of exFAT clusters (limited by implementation) */
                        -#define MAX_DIR		0x200000		/* Maximum size of FAT directory */
                        -#define MAX_DIR_EX	0x10000000		/* Maximum size of exFAT directory */
                        +/* Limits and boundaries */
                        +#define MAX_DIR		0x200000		/* Max size of FAT directory */
                        +#define MAX_DIR_EX	0x10000000		/* Max size of exFAT directory */
                        +#define MAX_FAT12	0xFF5			/* Max FAT12 clusters (differs from specs, but correct for real DOS/Windows behavior) */
                        +#define	MAX_FAT16	0xFFF5			/* Max FAT16 clusters (differs from specs, but correct for real DOS/Windows behavior) */
                        +#define	MAX_FAT32	0x0FFFFFF5		/* Max FAT32 clusters (not specified, practical limit) */
                        +#define	MAX_EXFAT	0x7FFFFFFD		/* Max exFAT clusters (differs from specs, implementation limit) */
                         
                         
                        -/* FatFs refers the members in the FAT structures as byte array instead of
                        -/ structure members because the structure is not binary compatible between
                        -/ different platforms */
                        +/* FatFs refers the FAT structure as simple byte array instead of structure member
                        +/ because the C structure is not binary compatible between different platforms */
                         
                         #define BS_JmpBoot			0		/* x86 jump instruction (3-byte) */
                         #define BS_OEMName			3		/* OEM name (8-byte) */
                        @@ -432,19 +377,61 @@ typedef struct {
                         #define BPB_FatSzEx			84		/* exFAT: FAT size [sector] (DWORD) */
                         #define BPB_DataOfsEx		88		/* exFAT: Data offset from top of the volume [sector] (DWORD) */
                         #define BPB_NumClusEx		92		/* exFAT: Number of clusters (DWORD) */
                        -#define BPB_RootClusEx		96		/* exFAT: Root directory cluster (DWORD) */
                        +#define BPB_RootClusEx		96		/* exFAT: Root directory start cluster (DWORD) */
                         #define BPB_VolIDEx			100		/* exFAT: Volume serial number (DWORD) */
                         #define BPB_FSVerEx			104		/* exFAT: File system version (WORD) */
                         #define BPB_VolFlagEx		106		/* exFAT: Volume flags (BYTE) */
                         #define BPB_ActFatEx		107		/* exFAT: Active FAT flags (BYTE) */
                        -#define BPB_BytsPerSecEx	108		/* exFAT: Log2 of sector size in byte (BYTE) */
                        -#define BPB_SecPerClusEx	109		/* exFAT: Log2 of cluster size in sector (BYTE) */
                        +#define BPB_BytsPerSecEx	108		/* exFAT: Log2 of sector size in unit of byte (BYTE) */
                        +#define BPB_SecPerClusEx	109		/* exFAT: Log2 of cluster size in unit of sector (BYTE) */
                         #define BPB_NumFATsEx		110		/* exFAT: Number of FATs (BYTE) */
                         #define BPB_DrvNumEx		111		/* exFAT: Physical drive number for int13h (BYTE) */
                         #define BPB_PercInUseEx		112		/* exFAT: Percent in use (BYTE) */
                         #define	BPB_RsvdEx			113		/* exFAT: Reserved (7-byte) */
                         #define BS_BootCodeEx		120		/* exFAT: Boot code (390-byte) */
                         
                        +#define	DIR_Name			0		/* Short file name (11-byte) */
                        +#define	DIR_Attr			11		/* Attribute (BYTE) */
                        +#define	DIR_NTres			12		/* Lower case flag (BYTE) */
                        +#define DIR_CrtTime10		13		/* Created time sub-second (BYTE) */
                        +#define	DIR_CrtTime			14		/* Created time (DWORD) */
                        +#define DIR_LstAccDate		18		/* Last accessed date (WORD) */
                        +#define	DIR_FstClusHI		20		/* Higher 16-bit of first cluster (WORD) */
                        +#define	DIR_ModTime			22		/* Modified time (DWORD) */
                        +#define	DIR_FstClusLO		26		/* Lower 16-bit of first cluster (WORD) */
                        +#define	DIR_FileSize		28		/* File size (DWORD) */
                        +#define	LDIR_Ord			0		/* LFN: LFN order and LLE flag (BYTE) */
                        +#define	LDIR_Attr			11		/* LFN: LFN attribute (BYTE) */
                        +#define	LDIR_Type			12		/* LFN: Entry type (BYTE) */
                        +#define	LDIR_Chksum			13		/* LFN: Checksum of the SFN (BYTE) */
                        +#define	LDIR_FstClusLO		26		/* LFN: MBZ field (WORD) */
                        +#define	XDIR_Type			0		/* exFAT: Type of exFAT directory entry (BYTE) */
                        +#define	XDIR_NumLabel		1		/* exFAT: Number of volume label characters (BYTE) */
                        +#define	XDIR_Label			2		/* exFAT: Volume label (11-WORD) */
                        +#define	XDIR_CaseSum		4		/* exFAT: Sum of case conversion table (DWORD) */
                        +#define	XDIR_NumSec			1		/* exFAT: Number of secondary entries (BYTE) */
                        +#define	XDIR_SetSum			2		/* exFAT: Sum of the set of directory entries (WORD) */
                        +#define	XDIR_Attr			4		/* exFAT: File attribute (WORD) */
                        +#define	XDIR_CrtTime		8		/* exFAT: Created time (DWORD) */
                        +#define	XDIR_ModTime		12		/* exFAT: Modified time (DWORD) */
                        +#define	XDIR_AccTime		16		/* exFAT: Last accessed time (DWORD) */
                        +#define	XDIR_CrtTime10		20		/* exFAT: Created time subsecond (BYTE) */
                        +#define	XDIR_ModTime10		21		/* exFAT: Modified time subsecond (BYTE) */
                        +#define	XDIR_CrtTZ			22		/* exFAT: Created timezone (BYTE) */
                        +#define	XDIR_ModTZ			23		/* exFAT: Modified timezone (BYTE) */
                        +#define	XDIR_AccTZ			24		/* exFAT: Last accessed timezone (BYTE) */
                        +#define	XDIR_GenFlags		33		/* exFAT: General secondary flags (WORD) */
                        +#define	XDIR_NumName		35		/* exFAT: Number of file name characters (BYTE) */
                        +#define	XDIR_NameHash		36		/* exFAT: Hash of file name (WORD) */
                        +#define XDIR_ValidFileSize	40		/* exFAT: Valid file size (QWORD) */
                        +#define	XDIR_FstClus		52		/* exFAT: First cluster of the file data (DWORD) */
                        +#define	XDIR_FileSize		56		/* exFAT: File/Directory size (QWORD) */
                        +
                        +#define	SZDIRE				32		/* Size of a directory entry */
                        +#define	DDEM				0xE5	/* Deleted directory entry mark set to DIR_Name[0] */
                        +#define	RDDEM				0x05	/* Replacement of the character collides with DDEM */
                        +#define	LLEF				0x40	/* Last long entry flag in LDIR_Ord */
                        +
                         #define	FSI_LeadSig			0		/* FAT32 FSI: Leading signature (DWORD) */
                         #define	FSI_StrucSig		484		/* FAT32 FSI: Structure signature (DWORD) */
                         #define	FSI_Free_Count		488		/* FAT32 FSI: Number of free clusters (DWORD) */
                        @@ -463,47 +450,68 @@ typedef struct {
                         #define PTE_StLba			8		/* MBR PTE: Start in LBA */
                         #define PTE_SizLba			12		/* MBR PTE: Size in LBA */
                         
                        -#define	DIR_Name			0		/* Short file name (11-byte) */
                        -#define	DIR_Attr			11		/* Attribute (BYTE) */
                        -#define	DIR_NTres			12		/* Lower case flag (BYTE) */
                        -#define DIR_CrtTime10		13		/* Created time sub-second (BYTE) */
                        -#define	DIR_CrtTime			14		/* Created time (DWORD) */
                        -#define DIR_LstAccDate		18		/* Last accessed date (WORD) */
                        -#define	DIR_FstClusHI		20		/* Higher 16-bit of first cluster (WORD) */
                        -#define	DIR_ModTime			22		/* Modified time (DWORD) */
                        -#define	DIR_FstClusLO		26		/* Lower 16-bit of first cluster (WORD) */
                        -#define	DIR_FileSize		28		/* File size (DWORD) */
                        -#define	LDIR_Ord			0		/* LFN entry order and LLE flag (BYTE) */
                        -#define	LDIR_Attr			11		/* LFN attribute (BYTE) */
                        -#define	LDIR_Type			12		/* LFN type (BYTE) */
                        -#define	LDIR_Chksum			13		/* Checksum of the SFN entry (BYTE) */
                        -#define	LDIR_FstClusLO		26		/* Must be zero (WORD) */
                        -#define	XDIR_Type			0		/* Type of exFAT directory entry (BYTE) */
                        -#define	XDIR_NumLabel		1		/* Number of volume label characters (BYTE) */
                        -#define	XDIR_Label			2		/* Volume label (11-WORD) */
                        -#define	XDIR_CaseSum		4		/* Sum of case conversion table (DWORD) */
                        -#define	XDIR_NumSec			1		/* Number of secondary entries (BYTE) */
                        -#define	XDIR_SetSum			2		/* Sum of the set of directory entries (WORD) */
                        -#define	XDIR_Attr			4		/* File attribute (WORD) */
                        -#define	XDIR_CrtTime		8		/* Created time (DWORD) */
                        -#define	XDIR_ModTime		12		/* Modified time (DWORD) */
                        -#define	XDIR_AccTime		16		/* Last accessed time (DWORD) */
                        -#define	XDIR_CrtTime10		20		/* Created time subsecond (BYTE) */
                        -#define	XDIR_ModTime10		21		/* Modified time subsecond (BYTE) */
                        -#define	XDIR_CrtTZ			22		/* Created timezone (BYTE) */
                        -#define	XDIR_ModTZ			23		/* Modified timezone (BYTE) */
                        -#define	XDIR_AccTZ			24		/* Last accessed timezone (BYTE) */
                        -#define	XDIR_GenFlags		33		/* Gneral secondary flags (WORD) */
                        -#define	XDIR_NumName		35		/* Number of file name characters (BYTE) */
                        -#define	XDIR_NameHash		36		/* Hash of file name (WORD) */
                        -#define XDIR_ValidFileSize	40		/* Valid file size (QWORD) */
                        -#define	XDIR_FstClus		52		/* First cluster of the file data (DWORD) */
                        -#define	XDIR_FileSize		56		/* File/Directory size (QWORD) */
                         
                        -#define	SZDIRE				32		/* Size of a directory entry */
                        -#define	LLEF				0x40	/* Last long entry flag in LDIR_Ord */
                        -#define	DDEM				0xE5	/* Deleted directory entry mark set to DIR_Name[0] */
                        -#define	RDDEM				0x05	/* Replacement of the character collides with DDEM */
                        +/* Post process after fatal error on file operation */
                        +#define	ABORT(fs, res)		{ fp->err = (BYTE)(res); LEAVE_FF(fs, res); }
                        +
                        +
                        +/* Reentrancy related */
                        +#if _FS_REENTRANT
                        +#if _USE_LFN == 1
                        +#error Static LFN work area cannot be used at thread-safe configuration
                        +#endif
                        +#define	ENTER_FF(fs)		{ if (!lock_fs(fs)) return FR_TIMEOUT; }
                        +#define	LEAVE_FF(fs, res)	{ unlock_fs(fs, res); return res; }
                        +#else
                        +#define	ENTER_FF(fs)
                        +#define LEAVE_FF(fs, res)	return res
                        +#endif
                        +
                        +
                        +/* Definitions of volume - partition conversion */
                        +#if _MULTI_PARTITION
                        +#define LD2PD(vol) VolToPart[vol].pd	/* Get physical drive number */
                        +#define LD2PT(vol) VolToPart[vol].pt	/* Get partition index */
                        +#else
                        +#define LD2PD(vol) (BYTE)(vol)	/* Each logical drive is bound to the same physical drive number */
                        +#define LD2PT(vol) 0			/* Find first valid partition or in SFD */
                        +#endif
                        +
                        +
                        +/* Definitions of sector size */
                        +#if (_MAX_SS < _MIN_SS) || (_MAX_SS != 512 && _MAX_SS != 1024 && _MAX_SS != 2048 && _MAX_SS != 4096) || (_MIN_SS != 512 && _MIN_SS != 1024 && _MIN_SS != 2048 && _MIN_SS != 4096)
                        +#error Wrong sector size configuration
                        +#endif
                        +#if _MAX_SS == _MIN_SS
                        +#define	SS(fs)	((UINT)_MAX_SS)	/* Fixed sector size */
                        +#else
                        +#define	SS(fs)	((fs)->ssize)	/* Variable sector size */
                        +#endif
                        +
                        +
                        +/* Timestamp */
                        +#if _FS_NORTC == 1
                        +#if _NORTC_YEAR < 1980 || _NORTC_YEAR > 2107 || _NORTC_MON < 1 || _NORTC_MON > 12 || _NORTC_MDAY < 1 || _NORTC_MDAY > 31
                        +#error Invalid _FS_NORTC settings
                        +#endif
                        +#define GET_FATTIME()	((DWORD)(_NORTC_YEAR - 1980) << 25 | (DWORD)_NORTC_MON << 21 | (DWORD)_NORTC_MDAY << 16)
                        +#else
                        +#define GET_FATTIME()	get_fattime()
                        +#endif
                        +
                        +
                        +/* File lock controls */
                        +#if _FS_LOCK != 0
                        +#if _FS_READONLY
                        +#error _FS_LOCK must be 0 at read-only configuration
                        +#endif
                        +typedef struct {
                        +	FATFS *fs;		/* Object ID 1, volume (NULL:blank entry) */
                        +	DWORD clu;		/* Object ID 2, containing directory (0:root) */
                        +	DWORD ofs;		/* Object ID 3, offset in the directory */
                        +	WORD ctr;		/* Object open counter, 0:none, 0x01..0xFF:read mode open count, 0x100:write mode */
                        +} FILESEM;
                        +#endif
                         
                         
                         
                        @@ -515,11 +523,11 @@ typedef struct {
                         
                         ---------------------------------------------------------------------------*/
                         
                        -/* Remark: Variables here without initial value shall be guaranteed zero/null
                        -/  at start-up. If not, either the linker or start-up routine being used is
                        +/* Remark: Variables defined here without initial value shall be guaranteed
                        +/  zero/null at start-up. If not, the linker option or start-up routine is
                         /  not compliance with C standard. */
                         
                        -#if _VOLUMES < 1 || _VOLUMES > 9
                        +#if _VOLUMES < 1 || _VOLUMES > 10
                         #error Wrong _VOLUMES setting
                         #endif
                         static FATFS *FatFs[_VOLUMES];	/* Pointer to the file system objects (logical drives) */
                        @@ -533,27 +541,29 @@ static BYTE CurrVol;			/* Current drive */
                         static FILESEM Files[_FS_LOCK];	/* Open object lock semaphores */
                         #endif
                         
                        -#if _USE_LFN == 0			/* Non-LFN configuration */
                        +#if _USE_LFN == 0		/* Non-LFN configuration */
                         #define	DEF_NAMBUF
                         #define INIT_NAMBUF(fs)
                         #define	FREE_NAMBUF()
                        -#else
                        +
                        +#else					/* LFN configuration */
                         #if _MAX_LFN < 12 || _MAX_LFN > 255
                        -#error Wrong _MAX_LFN setting
                        +#error Wrong _MAX_LFN value
                         #endif
                        +#define MAXDIRB(nc)	((nc + 44U) / 15 * SZDIRE)
                         
                         #if _USE_LFN == 1		/* LFN enabled with static working buffer */
                         #if _FS_EXFAT
                        -static BYTE	DirBuf[SZDIRE*19];	/* Directory entry block scratchpad buffer (19 entries in size) */
                        +static BYTE	DirBuf[MAXDIRB(_MAX_LFN)];	/* Directory entry block scratchpad buffer */
                         #endif
                        -static WCHAR LfnBuf[_MAX_LFN+1];	/* LFN enabled with static working buffer */
                        +static WCHAR LfnBuf[_MAX_LFN + 1];	/* LFN enabled with static working buffer */
                         #define	DEF_NAMBUF
                         #define INIT_NAMBUF(fs)
                         #define	FREE_NAMBUF()
                         
                         #elif _USE_LFN == 2 	/* LFN enabled with dynamic working buffer on the stack */
                         #if _FS_EXFAT
                        -#define	DEF_NAMBUF		WCHAR lbuf[_MAX_LFN+1]; BYTE dbuf[SZDIRE*19];
                        +#define	DEF_NAMBUF		WCHAR lbuf[_MAX_LFN+1]; BYTE dbuf[MAXDIRB(_MAX_LFN)];
                         #define INIT_NAMBUF(fs)	{ (fs)->lfnbuf = lbuf; (fs)->dirbuf = dbuf; }
                         #define	FREE_NAMBUF()
                         #else
                        @@ -565,7 +575,7 @@ static WCHAR LfnBuf[_MAX_LFN+1];	/* LFN enabled with static working buffer */
                         #elif _USE_LFN == 3 	/* LFN enabled with dynamic working buffer on the heap */
                         #if _FS_EXFAT
                         #define	DEF_NAMBUF		WCHAR *lfn;
                        -#define INIT_NAMBUF(fs)	{ lfn = ff_memalloc((_MAX_LFN+1)*2 + SZDIRE*19); if (!lfn) LEAVE_FF(fs, FR_NOT_ENOUGH_CORE); (fs)->lfnbuf = lfn; (fs)->dirbuf = (BYTE*)(lfn+_MAX_LFN+1); }
                        +#define INIT_NAMBUF(fs)	{ lfn = ff_memalloc((_MAX_LFN+1)*2 + MAXDIRB(_MAX_LFN)); if (!lfn) LEAVE_FF(fs, FR_NOT_ENOUGH_CORE); (fs)->lfnbuf = lfn; (fs)->dirbuf = (BYTE*)(lfn+_MAX_LFN+1); }
                         #define	FREE_NAMBUF()	ff_memfree(lfn)
                         #else
                         #define	DEF_NAMBUF		WCHAR *lfn;
                        @@ -575,8 +585,9 @@ static WCHAR LfnBuf[_MAX_LFN+1];	/* LFN enabled with static working buffer */
                         
                         #else
                         #error Wrong _USE_LFN setting
                        +
                         #endif
                        -#endif
                        +#endif	/* else _USE_LFN == 0 */
                         
                         #ifdef _EXCVT
                         static const BYTE ExCvt[] = _EXCVT;	/* Upper conversion table for SBCS extended characters */
                        @@ -684,7 +695,9 @@ void mem_cpy (void* dst, const void* src, UINT cnt) {
                         	const BYTE *s = (const BYTE*)src;
                         
                         	if (cnt) {
                        -		do *d++ = *s++; while (--cnt);
                        +		do {
                        +			*d++ = *s++;
                        +		} while (--cnt);
                         	}
                         }
                         
                        @@ -693,7 +706,9 @@ static
                         void mem_set (void* dst, int val, UINT cnt) {
                         	BYTE *d = (BYTE*)dst;
                         
                        -	do *d++ = (BYTE)val; while (--cnt);
                        +	do {
                        +		*d++ = (BYTE)val;
                        +	} while (--cnt);
                         }
                         
                         /* Compare memory block */
                        @@ -728,7 +743,7 @@ int lock_fs (
                         	FATFS* fs		/* File system object */
                         )
                         {
                        -	return ff_req_grant(fs->sobj);
                        +	return (fs && ff_req_grant(fs->sobj)) ? 1 : 0;
                         }
                         
                         
                        @@ -1030,17 +1045,21 @@ DWORD get_fat (	/* 0xFFFFFFFF:Disk error, 1:Internal error, 2..0x7FFFFFFF:Cluste
                         						break;
                         					}
                         				}
                        -				if (obj->stat == 3 && cofs < obj->n_cont) {	/* Is it in the contiguous part? */
                        +				if (obj->stat == 3 && cofs < obj->n_cont) {	/* Is it in the 1st fragment? */
                         					val = clst + 1; 	/* Generate the value */
                         					break;
                         				}
                         				if (obj->stat != 2) {	/* Get value from FAT if FAT chain is valid */
                        -					if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break;
                        -					val = ld_dword(fs->win + clst * 4 % SS(fs)) & 0x7FFFFFFF;
                        +					if (obj->n_frag != 0) {	/* Is it on the growing edge? */
                        +						val = 0x7FFFFFFF;	/* Generate EOC */
                        +					} else {
                        +						if (move_window(fs, fs->fatbase + (clst / (SS(fs) / 4))) != FR_OK) break;
                        +						val = ld_dword(fs->win + clst * 4 % SS(fs)) & 0x7FFFFFFF;
                        +					}
                         					break;
                         				}
                         			}
                        -			/* go next */
                        +			/* go to default */
                         #endif
                         		default:
                         			val = 1;	/* Internal error */
                        @@ -1069,7 +1088,6 @@ FRESULT put_fat (	/* FR_OK(0):succeeded, !=0:error */
                         	BYTE *p;
                         	FRESULT res = FR_INT_ERR;
                         
                        -
                         	if (clst >= 2 && clst < fs->n_fatent) {	/* Check if in valid range */
                         		switch (fs->fs_type) {
                         		case FS_FAT12 :	/* Bitfield items */
                        @@ -1120,12 +1138,12 @@ FRESULT put_fat (	/* FR_OK(0):succeeded, !=0:error */
                         /* exFAT: Accessing FAT and Allocation Bitmap                            */
                         /*-----------------------------------------------------------------------*/
                         
                        -/*---------------------------------------------*/
                        -/* exFAT: Find a contiguous free cluster block */
                        -/*---------------------------------------------*/
                        +/*--------------------------------------*/
                        +/* Find a contiguous free cluster block */
                        +/*--------------------------------------*/
                         
                         static
                        -DWORD find_bitmap (	/* 0:No free cluster, 2..:Free cluster found, 0xFFFFFFFF:Disk error */
                        +DWORD find_bitmap (	/* 0:Not found, 2..:Cluster block found, 0xFFFFFFFF:Disk error */
                         	FATFS* fs,	/* File system object */
                         	DWORD clst,	/* Cluster number to scan from */
                         	DWORD ncl	/* Number of contiguous clusters to find (1..) */
                        @@ -1146,12 +1164,12 @@ DWORD find_bitmap (	/* 0:No free cluster, 2..:Free cluster found, 0xFFFFFFFF:Dis
                         			do {
                         				bv = fs->win[i] & bm; bm <<= 1;		/* Get bit value */
                         				if (++val >= fs->n_fatent - 2) {	/* Next cluster (with wrap-around) */
                        -					val = 0; bm = 0; i = 4096;
                        +					val = 0; bm = 0; i = SS(fs);
                         				}
                         				if (!bv) {	/* Is it a free cluster? */
                        -					if (++ctr == ncl) return scl + 2;	/* Check run length */
                        +					if (++ctr == ncl) return scl + 2;	/* Check if run length is sufficient for required */
                         				} else {
                        -					scl = val; ctr = 0;		/* Encountered a live cluster, restart to scan */
                        +					scl = val; ctr = 0;		/* Encountered a cluster in-use, restart to scan */
                         				}
                         				if (val == clst) return 0;	/* All cluster scanned? */
                         			} while (bm);
                        @@ -1161,9 +1179,9 @@ DWORD find_bitmap (	/* 0:No free cluster, 2..:Free cluster found, 0xFFFFFFFF:Dis
                         }
                         
                         
                        -/*------------------------------------*/
                        -/* exFAT: Set/Clear a block of bitmap */
                        -/*------------------------------------*/
                        +/*----------------------------------------*/
                        +/* Set/Clear a block of allocation bitmap */
                        +/*----------------------------------------*/
                         
                         static
                         FRESULT change_bitmap (
                        @@ -1177,7 +1195,6 @@ FRESULT change_bitmap (
                         	UINT i;
                         	DWORD sect;
                         
                        -
                         	clst -= 2;	/* The first bit corresponds to cluster #2 */
                         	sect = fs->database + clst / 8 / SS(fs);	/* Sector address (assuming bitmap is located top of the cluster heap) */
                         	i = clst / 8 % SS(fs);						/* Byte offset in the sector */
                        @@ -1199,11 +1216,11 @@ FRESULT change_bitmap (
                         
                         
                         /*---------------------------------------------*/
                        -/* Complement contiguous part of the FAT chain */
                        +/* Fill the first fragment of the FAT chain    */
                         /*---------------------------------------------*/
                         
                         static
                        -FRESULT fill_fat_chain (
                        +FRESULT fill_first_frag (
                         	_FDID* obj	/* Pointer to the corresponding object */
                         )
                         {
                        @@ -1220,6 +1237,28 @@ FRESULT fill_fat_chain (
                         	return FR_OK;
                         }
                         
                        +
                        +/*---------------------------------------------*/
                        +/* Fill the last fragment of the FAT chain     */
                        +/*---------------------------------------------*/
                        +
                        +static
                        +FRESULT fill_last_frag (
                        +	_FDID* obj,	/* Pointer to the corresponding object */
                        +	DWORD lcl,	/* Last cluster of the fragment */
                        +	DWORD term	/* Value to set the last FAT entry */
                        +)
                        +{
                        +	FRESULT res;
                        +
                        +	while (obj->n_frag > 0) {	/* Create the last chain on the FAT */
                        +		res = put_fat(obj->fs, lcl - obj->n_frag + 1, (obj->n_frag > 1) ? lcl - obj->n_frag + 2 : term);
                        +		if (res != FR_OK) return res;
                        +		obj->n_frag--;
                        +	}
                        +	return FR_OK;
                        +}
                        +
                         #endif	/* _FS_EXFAT && !_FS_READONLY */
                         
                         
                        @@ -1270,7 +1309,7 @@ FRESULT remove_chain (	/* FR_OK(0):succeeded, !=0:error */
                         #if _FS_EXFAT || _USE_TRIM
                         		if (ecl + 1 == nxt) {	/* Is next cluster contiguous? */
                         			ecl = nxt;
                        -		} else {				/* End of contiguous cluster block */ 
                        +		} else {				/* End of contiguous cluster block */
                         #if _FS_EXFAT
                         			if (fs->fs_type == FS_EXFAT) {
                         				res = change_bitmap(fs, scl, ecl - scl + 1, 0);	/* Mark the cluster block 'free' on the bitmap */
                        @@ -1290,10 +1329,10 @@ FRESULT remove_chain (	/* FR_OK(0):succeeded, !=0:error */
                         
                         #if _FS_EXFAT
                         	if (fs->fs_type == FS_EXFAT) {
                        -		if (pclst == 0) {	/* Does object have no chain? */
                        +		if (pclst == 0) {	/* Does the object have no chain? */
                         			obj->stat = 0;		/* Change the object status 'initial' */
                         		} else {
                        -			if (obj->stat == 3 && pclst >= obj->sclust && pclst <= obj->sclust + obj->n_cont) {	/* Did the chain got contiguous? */
                        +			if (obj->stat == 3 && pclst >= obj->sclust && pclst <= obj->sclust + obj->n_cont) {	/* Did the chain get contiguous? */
                         				obj->stat = 2;	/* Change the object status 'contiguous' */
                         			}
                         		}
                        @@ -1325,7 +1364,7 @@ DWORD create_chain (	/* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk err
                         	}
                         	else {				/* Stretch current chain */
                         		cs = get_fat(obj, clst);			/* Check the cluster status */
                        -		if (cs < 2) return 1;				/* Invalid value */
                        +		if (cs < 2) return 1;				/* Invalid FAT value */
                         		if (cs == 0xFFFFFFFF) return cs;	/* A disk error occurred */
                         		if (cs < fs->n_fatent) return cs;	/* It is already followed by next cluster */
                         		scl = clst;
                        @@ -1339,13 +1378,22 @@ DWORD create_chain (	/* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk err
                         		if (res == FR_INT_ERR) return 1;
                         		if (res == FR_DISK_ERR) return 0xFFFFFFFF;
                         		if (clst == 0) {							/* Is it a new chain? */
                        -			obj->stat = 2;							/* Set status 'contiguous chain' */
                        -		} else {									/* This is a stretched chain */
                        +			obj->stat = 2;							/* Set status 'contiguous' */
                        +		} else {									/* It is a stretched chain */
                         			if (obj->stat == 2 && ncl != scl + 1) {	/* Is the chain got fragmented? */
                         				obj->n_cont = scl - obj->sclust;	/* Set size of the contiguous part */
                         				obj->stat = 3;						/* Change status 'just fragmented' */
                         			}
                         		}
                        +		if (obj->stat != 2) {	/* Is the file non-contiguous? */
                        +			if (ncl == clst + 1) {	/* Is the cluster next to previous one? */
                        +				obj->n_frag = obj->n_frag ? obj->n_frag + 1 : 2;	/* Increment size of last framgent */
                        +			} else {				/* New fragment */
                        +				if (obj->n_frag == 0) obj->n_frag = 1;
                        +				res = fill_last_frag(obj, clst, ncl);	/* Fill last fragment on the FAT and link it to new one */
                        +				if (res == FR_OK) obj->n_frag = 1;
                        +			}
                        +		}
                         	} else
                         #endif
                         	{	/* On the FAT12/16/32 volume */
                        @@ -1361,23 +1409,18 @@ DWORD create_chain (	/* 0:No free cluster, 1:Internal error, 0xFFFFFFFF:Disk err
                         			if (cs == 1 || cs == 0xFFFFFFFF) return cs;	/* An error occurred */
                         			if (ncl == scl) return 0;		/* No free cluster */
                         		}
                        -	}
                        -
                        -	if (_FS_EXFAT && fs->fs_type == FS_EXFAT && obj->stat == 2) {	/* Is it a contiguous chain? */
                        -		res = FR_OK;						/* FAT does not need to be written */
                        -	} else {
                         		res = put_fat(fs, ncl, 0xFFFFFFFF);	/* Mark the new cluster 'EOC' */
                        -		if (res == FR_OK && clst) {
                        +		if (res == FR_OK && clst != 0) {
                         			res = put_fat(fs, clst, ncl);	/* Link it from the previous one if needed */
                         		}
                         	}
                         
                         	if (res == FR_OK) {			/* Update FSINFO if function succeeded. */
                         		fs->last_clst = ncl;
                        -		if (fs->free_clst < fs->n_fatent - 2) fs->free_clst--;
                        +		if (fs->free_clst <= fs->n_fatent - 2) fs->free_clst--;
                         		fs->fsi_flag |= 1;
                         	} else {
                        -		ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1;	/* Failed. Create error status */
                        +		ncl = (res == FR_DISK_ERR) ? 0xFFFFFFFF : 1;	/* Failed. Generate error status */
                         	}
                         
                         	return ncl;		/* Return new cluster number or error status */
                        @@ -1519,7 +1562,7 @@ FRESULT dir_next (	/* FR_OK(0):succeeded, FR_NO_FILE:End of table, FR_DENIED:Cou
                         					}
                         					fs->winsect -= n;							/* Restore window offset */
                         #else
                        -					if (!stretch) dp->sect = 0;					/* If no stretch, report EOT (this is to suppress warning) */
                        +					if (!stretch) dp->sect = 0;					/* (this line is to suppress compiler warning) */
                         					dp->sect = 0; return FR_NO_FILE;			/* Report EOT */
                         #endif
                         				}
                        @@ -1676,9 +1719,9 @@ int pick_lfn (			/* 1:succeeded, 0:buffer overflow or invalid LFN entry */
                         	WCHAR wc, uc;
                         
                         
                        -	if (ld_word(dir + LDIR_FstClusLO) != 0) return 0;	/* Check LDIR_FstClusLO */
                        +	if (ld_word(dir + LDIR_FstClusLO) != 0) return 0;	/* Check LDIR_FstClusLO is 0 */
                         
                        -	i = ((dir[LDIR_Ord] & 0x3F) - 1) * 13;	/* Offset in the LFN buffer */
                        +	i = ((dir[LDIR_Ord] & ~LLEF) - 1) * 13;	/* Offset in the LFN buffer */
                         
                         	for (wc = 1, s = 0; s < 13; s++) {		/* Process all characters in the entry */
                         		uc = ld_word(dir + LfnOfs[s]);		/* Pick an LFN character */
                        @@ -1809,7 +1852,9 @@ BYTE sum_sfn (
                         	BYTE sum = 0;
                         	UINT n = 11;
                         
                        -	do sum = (sum >> 1) + (sum << 7) + *dir++; while (--n);
                        +	do {
                        +		sum = (sum >> 1) + (sum << 7) + *dir++;
                        +	} while (--n);
                         	return sum;
                         }
                         
                        @@ -1893,30 +1938,26 @@ void get_xdir_info (
                         #endif
                         
                         	/* Get file name */
                        +	di = 0;
                         #if _LFN_UNICODE
                        -	if (dirb[XDIR_NumName] <= _MAX_LFN) {
                        -		for (si = SZDIRE * 2, di = 0; di < dirb[XDIR_NumName]; si += 2, di++) {
                        -			if ((si % SZDIRE) == 0) si += 2;	/* Skip entry type field */
                        -			w = ld_word(dirb + si);				/* Get a character */
                        -			fno->fname[di] = w;					/* Store it */
                        -		}
                        -	} else {
                        -		di = 0;	/* Buffer overflow and inaccessible object */
                        +	for (si = SZDIRE * 2; di < dirb[XDIR_NumName]; si += 2, di++) {
                        +		if ((si % SZDIRE) == 0) si += 2;		/* Skip entry type field */
                        +		w = ld_word(dirb + si);					/* Get a character */
                        +		if (di >= _MAX_LFN) { di = 0; break; }	/* Buffer overflow --> inaccessible object name */
                        +		fno->fname[di] = w;						/* Store it */
                         	}
                         #else
                        -	for (si = SZDIRE * 2, di = nc = 0; nc < dirb[XDIR_NumName]; si += 2, nc++) {
                        -		if ((si % SZDIRE) == 0) si += 2;	/* Skip entry type field */
                        -		w = ld_word(dirb + si);				/* Get a character */
                        -		w = ff_convert(w, 0);				/* Unicode -> OEM */
                        -		if (w == 0) { di = 0; break; }		/* Could not be converted and inaccessible object */
                        -		if (_DF1S && w >= 0x100) {			/* Put 1st byte if it is a DBC (always false at SBCS cfg) */
                        -			fno->fname[di++] = (char)(w >> 8);
                        +	for (si = SZDIRE * 2, nc = 0; nc < dirb[XDIR_NumName]; si += 2, nc++) {
                        +		if ((si % SZDIRE) == 0) si += 2;		/* Skip entry type field */
                        +		w = ff_convert(ld_word(dirb + si), 0);	/* Get a character and Unicode -> OEM */
                        +		if (_DF1S && w >= 0x100) {				/* Is it a double byte char? (always false at SBCS cfg) */
                        +			fno->fname[di++] = (char)(w >> 8);	/* Put 1st byte of the DBC */
                         		}
                        -		if (di >= _MAX_LFN) { di = 0; break; }	/* Buffer overflow and inaccessible object */
                        +		if (w == 0 || di >= _MAX_LFN) { di = 0; break; }	/* Invalid char or buffer overflow --> inaccessible object name */
                         		fno->fname[di++] = (char)w;
                         	}
                         #endif
                        -	if (di == 0) fno->fname[di++] = '?';	/* Inaccessible object? */
                        +	if (di == 0) fno->fname[di++] = '?';	/* Inaccessible object name? */
                         	fno->fname[di] = 0;						/* Terminate file name */
                         
                         	fno->altname[0] = 0;							/* No SFN */
                        @@ -1939,7 +1980,7 @@ FRESULT load_xdir (	/* FR_INT_ERR: invalid entry block */
                         )
                         {
                         	FRESULT res;
                        -	UINT i, nent;
                        +	UINT i, sz_ent;
                         	BYTE* dirb = dp->obj.fs->dirbuf;	/* Pointer to the on-memory direcotry entry block 85+C0+C1s */
                         
                         
                        @@ -1947,8 +1988,9 @@ FRESULT load_xdir (	/* FR_INT_ERR: invalid entry block */
                         	res = move_window(dp->obj.fs, dp->sect);
                         	if (res != FR_OK) return res;
                         	if (dp->dir[XDIR_Type] != 0x85) return FR_INT_ERR;
                        -	mem_cpy(dirb, dp->dir, SZDIRE);
                        -	nent = dirb[XDIR_NumSec] + 1;
                        +	mem_cpy(dirb + 0, dp->dir, SZDIRE);
                        +	sz_ent = (dirb[XDIR_NumSec] + 1) * SZDIRE;
                        +	if (sz_ent < 3 * SZDIRE || sz_ent > 19 * SZDIRE) return FR_INT_ERR;
                         
                         	/* Load C0 entry */
                         	res = dir_next(dp, 0);
                        @@ -1957,40 +1999,39 @@ FRESULT load_xdir (	/* FR_INT_ERR: invalid entry block */
                         	if (res != FR_OK) return res;
                         	if (dp->dir[XDIR_Type] != 0xC0) return FR_INT_ERR;
                         	mem_cpy(dirb + SZDIRE, dp->dir, SZDIRE);
                        +	if (MAXDIRB(dirb[XDIR_NumName]) > sz_ent) return FR_INT_ERR;
                         
                         	/* Load C1 entries */
                        -	if (nent < 3 || nent > 19) return FR_NO_FILE;
                        -	i = SZDIRE * 2; nent *= SZDIRE;
                        +	i = SZDIRE * 2;	/* C1 offset */
                         	do {
                         		res = dir_next(dp, 0);
                         		if (res != FR_OK) return res;
                         		res = move_window(dp->obj.fs, dp->sect);
                         		if (res != FR_OK) return res;
                         		if (dp->dir[XDIR_Type] != 0xC1) return FR_INT_ERR;
                        -		mem_cpy(dirb + i, dp->dir, SZDIRE);
                        -		i += SZDIRE;
                        -	} while (i < nent);
                        -
                        -	/* Sanity check */
                        -	if (xdir_sum(dirb) != ld_word(dirb + XDIR_SetSum)) return FR_INT_ERR;
                        +		if (i < MAXDIRB(_MAX_LFN)) mem_cpy(dirb + i, dp->dir, SZDIRE);
                        +	} while ((i += SZDIRE) < sz_ent);
                         
                        +	/* Sanity check (do it when accessible object name) */
                        +	if (i <= MAXDIRB(_MAX_LFN)) {
                        +		if (xdir_sum(dirb) != ld_word(dirb + XDIR_SetSum)) return FR_INT_ERR;
                        +	}
                         	return FR_OK;
                         }
                         
                         
                        -#if !_FS_READONLY || _FS_RPATH != 0 
                        +#if !_FS_READONLY || _FS_RPATH != 0
                         /*------------------------------------------------*/
                         /* exFAT: Load the object's directory entry block */
                         /*------------------------------------------------*/
                         static
                         FRESULT load_obj_dir (	
                         	DIR* dp,			/* Blank directory object to be used to access containing direcotry */
                        -	const _FDID* obj	/* Object with containing directory information */
                        +	const _FDID* obj	/* Object with its containing directory information */
                         )
                         {
                         	FRESULT res;
                         
                        -
                         	/* Open object containing directory */
                         	dp->obj.fs = obj->fs;
                         	dp->obj.sclust = obj->c_scl;
                        @@ -1998,7 +2039,7 @@ FRESULT load_obj_dir (
                         	dp->obj.objsize = obj->c_size & 0xFFFFFF00;
                         	dp->blk_ofs = obj->c_ofs;
                         
                        -	res = dir_sdi(dp, dp->blk_ofs);	/* Goto the block location */
                        +	res = dir_sdi(dp, dp->blk_ofs);	/* Goto object's entry block */
                         	if (res == FR_OK) {
                         		res = load_xdir(dp);		/* Load the object's entry block */
                         	}
                        @@ -2055,24 +2096,25 @@ void create_xdir (
                         	WCHAR chr;
                         
                         
                        -	mem_set(dirb, 0, 2 * SZDIRE);			/* Initialize 85+C0 entry */
                        +	/* Create 85+C0 entry */
                        +	mem_set(dirb, 0, 2 * SZDIRE);
                         	dirb[XDIR_Type] = 0x85;
                         	dirb[XDIR_Type + SZDIRE] = 0xC0;
                        -	st_word(dirb + XDIR_NameHash, xname_sum(lfn));	/* Set name hash */
                         
                        -	i = SZDIRE * 2;	/* C1 offset */
                        -	nc = 0; nb = 1; chr = 1;
                        +	/* Create C1 entries */
                        +	nc = 0; nb = 1; chr = 1; i = SZDIRE * 2;
                         	do {
                         		dirb[i++] = 0xC1; dirb[i++] = 0;	/* Entry type C1 */
                         		do {	/* Fill name field */
                         			if (chr && (chr = lfn[nc]) != 0) nc++;	/* Get a character if exist */
                        -			st_word(dirb + i, chr); i += 2;	/* Store it */
                        -		} while (i % SZDIRE);
                        +			st_word(dirb + i, chr); 		/* Store it */
                        +		} while ((i += 2) % SZDIRE != 0);
                         		nb++;
                         	} while (lfn[nc]);	/* Fill next entry if any char follows */
                         
                         	dirb[XDIR_NumName] = nc;	/* Set name length */
                        -	dirb[XDIR_NumSec] = nb;		/* Set number of C0+C1s */
                        +	dirb[XDIR_NumSec] = nb;		/* Set block length */
                        +	st_word(dirb + XDIR_NameHash, xname_sum(lfn));	/* Set name hash */
                         }
                         
                         #endif	/* !_FS_READONLY */
                        @@ -2102,7 +2144,9 @@ FRESULT dir_read (
                         		res = move_window(fs, dp->sect);
                         		if (res != FR_OK) break;
                         		c = dp->dir[DIR_Name];	/* Test for the entry type */
                        -		if (c == 0) { res = FR_NO_FILE; break; }	/* Reached to end of the directory */
                        +		if (c == 0) {
                        +			res = FR_NO_FILE; break; /* Reached to end of the directory */
                        +		}
                         #if _FS_EXFAT
                         		if (fs->fs_type == FS_EXFAT) {	/* On the exFAT volume */
                         			if (_USE_LABEL && vol) {
                        @@ -2183,7 +2227,10 @@ FRESULT dir_find (	/* FR_OK(0):succeeded, !=0:error */
                         		WORD hash = xname_sum(fs->lfnbuf);		/* Hash value of the name to find */
                         
                         		while ((res = dir_read(dp, 0)) == FR_OK) {	/* Read an item */
                        -			if (ld_word(fs->dirbuf + XDIR_NameHash) != hash) continue;	/* Skip the comparison if hash value mismatched */
                        +#if _MAX_LFN < 255
                        +			if (fs->dirbuf[XDIR_NumName] > _MAX_LFN) continue;			/* Skip comparison if inaccessible object name */
                        +#endif
                        +			if (ld_word(fs->dirbuf + XDIR_NameHash) != hash) continue;	/* Skip comparison if hash mismatched */
                         			for (nc = fs->dirbuf[XDIR_NumName], di = SZDIRE * 2, ni = 0; nc; nc--, di += 2, ni++) {	/* Compare the name */
                         				if ((di % SZDIRE) == 0) di += 2;
                         				if (ff_wtoupper(ld_word(fs->dirbuf + di)) != ff_wtoupper(fs->lfnbuf[ni])) break;
                        @@ -2263,19 +2310,20 @@ FRESULT dir_register (	/* FR_OK:succeeded, FR_DENIED:no free entry or too many S
                         		nent = (nlen + 14) / 15 + 2;	/* Number of entries to allocate (85+C0+C1s) */
                         		res = dir_alloc(dp, nent);		/* Allocate entries */
                         		if (res != FR_OK) return res;
                        -		dp->blk_ofs = dp->dptr - SZDIRE * (nent - 1);			/* Set block position */
                        +		dp->blk_ofs = dp->dptr - SZDIRE * (nent - 1);	/* Set the allocated entry block offset */
                         
                         		if (dp->obj.sclust != 0 && (dp->obj.stat & 4)) {	/* Has the sub-directory been stretched? */
                        -			dp->obj.stat &= 3;
                        -			dp->obj.objsize += (DWORD)fs->csize * SS(fs);	/* Increase object size by cluster size */
                        -			res = fill_fat_chain(&dp->obj);	/* Complement FAT chain if needed */
                        +			dp->obj.objsize += (DWORD)fs->csize * SS(fs);	/* Increase the directory size by cluster size */
                        +			res = fill_first_frag(&dp->obj);				/* Fill first fragment on the FAT if needed */
                        +			if (res != FR_OK) return res;
                        +			res = fill_last_frag(&dp->obj, dp->clust, 0xFFFFFFFF);	/* Fill last fragment on the FAT if needed */
                        +			if (res != FR_OK) return res;
                        +			res = load_obj_dir(&dj, &dp->obj);				/* Load the object status */
                         			if (res != FR_OK) return res;
                        -			res = load_obj_dir(&dj, &dp->obj);
                        -			if (res != FR_OK) return res;	/* Load the object status */
                         			st_qword(fs->dirbuf + XDIR_FileSize, dp->obj.objsize);		/* Update the allocation status */
                         			st_qword(fs->dirbuf + XDIR_ValidFileSize, dp->obj.objsize);
                         			fs->dirbuf[XDIR_GenFlags] = dp->obj.stat | 1;
                        -			res = store_xdir(&dj);			/* Store the object status */
                        +			res = store_xdir(&dj);							/* Store the object status */
                         			if (res != FR_OK) return res;
                         		}
                         
                        @@ -2454,7 +2502,7 @@ void get_fileinfo (		/* No return code */
                         #endif
                         		fno->altname[j] = c;
                         		if (!lfv) {
                        -			if (IsUpper(c) && (dp->dir[DIR_NTres] & (i >= 9 ? NS_EXT : NS_BODY))) {
                        +			if (IsUpper(c) && (dp->dir[DIR_NTres] & ((i >= 9) ? NS_EXT : NS_BODY))) {
                         				c += 0x20;			/* To lower */
                         			}
                         			fno->fname[j] = c;
                        @@ -2775,14 +2823,16 @@ FRESULT follow_path (	/* FR_OK(0): successful, !=0: error code */
                         
                         #if _FS_RPATH != 0
                         	if (*path != '/' && *path != '\\') {	/* Without heading separator */
                        -		obj->sclust = fs->cdir;				/* Start from the current directory */
                        +		obj->sclust = fs->cdir;				/* Start from current directory */
                         	} else
                         #endif
                         	{										/* With heading separator */
                         		while (*path == '/' || *path == '\\') path++;	/* Strip heading separator */
                        -		obj->sclust = 0;					/* Start from the root directory */
                        +		obj->sclust = 0;					/* Start from root directory */
                         	}
                        -#if _FS_EXFAT && _FS_RPATH != 0
                        +#if _FS_EXFAT
                        +	obj->n_frag = 0;	/* Invalidate last fragment counter of the object */
                        +#if _FS_RPATH != 0
                         	if (fs->fs_type == FS_EXFAT && obj->sclust) {	/* Retrieve the sub-directory status if needed */
                         		DIR dj;
                         
                        @@ -2794,6 +2844,7 @@ FRESULT follow_path (	/* FR_OK(0): successful, !=0: error code */
                         		obj->objsize = ld_dword(fs->dirbuf + XDIR_FileSize);
                         		obj->stat = fs->dirbuf[XDIR_GenFlags] & 2;
                         	}
                        +#endif
                         #endif
                         
                         	if ((UINT)*path < ' ') {				/* Null path name is the origin directory itself */
                        @@ -2824,8 +2875,8 @@ FRESULT follow_path (	/* FR_OK(0): successful, !=0: error code */
                         				res = FR_NO_PATH; break;
                         			}
                         #if _FS_EXFAT
                        -			if (fs->fs_type == FS_EXFAT) {
                        -				obj->c_scl = obj->sclust;		/* Save containing directory information for next dir */
                        +			if (fs->fs_type == FS_EXFAT) {		/* Save containing directory information for next dir */
                        +				obj->c_scl = obj->sclust;
                         				obj->c_size = ((DWORD)obj->objsize & 0xFFFFFF00) | obj->stat;
                         				obj->c_ofs = dp->blk_ofs;
                         				obj->sclust = ld_dword(fs->dirbuf + XDIR_FstClus);	/* Open next directory */
                        @@ -2858,7 +2909,7 @@ int get_ldnumber (		/* Returns logical drive number (-1:invalid drive) */
                         	UINT i;
                         	int vol = -1;
                         #if _STR_VOLUME_ID		/* Find string drive id */
                        -	static const char* const str[] = {_VOLUME_STRS};
                        +	static const char* const volid[] = {_VOLUME_STRS};
                         	const char *sp;
                         	char c;
                         	TCHAR tc;
                        @@ -2869,7 +2920,7 @@ int get_ldnumber (		/* Returns logical drive number (-1:invalid drive) */
                         		for (tt = *path; (UINT)*tt >= (_USE_LFN ? ' ' : '!') && *tt != ':'; tt++) ;	/* Find ':' in the path */
                         		if (*tt == ':') {	/* If a ':' is exist in the path name */
                         			tp = *path;
                        -			i = *tp++ - '0'; 
                        +			i = *tp++ - '0';
                         			if (i < 10 && tp == tt) {	/* Is there a numeric drive id? */
                         				if (i < _VOLUMES) {	/* If a drive id is found, get the value and strip it */
                         					vol = (int)i;
                        @@ -2880,7 +2931,7 @@ int get_ldnumber (		/* Returns logical drive number (-1:invalid drive) */
                         			 else {	/* No numeric drive number, find string drive id */
                         				i = 0; tt++;
                         				do {
                        -					sp = str[i]; tp = *path;
                        +					sp = volid[i]; tp = *path;
                         					do {	/* Compare a string drive id with path name */
                         						c = *sp++; tc = *tp++;
                         						if (IsLower(tc)) tc -= 0x20;
                        @@ -2913,13 +2964,13 @@ int get_ldnumber (		/* Returns logical drive number (-1:invalid drive) */
                         static
                         BYTE check_fs (	/* 0:FAT, 1:exFAT, 2:Valid BS but not FAT, 3:Not a BS, 4:Disk error */
                         	FATFS* fs,	/* File system object */
                        -	DWORD sect	/* Sector# (lba) to check if it is an FAT-VBR or not */
                        +	DWORD sect	/* Sector# (lba) to load and check if it is an FAT-VBR or not */
                         )
                         {
                         	fs->wflag = 0; fs->winsect = 0xFFFFFFFF;		/* Invaidate window */
                         	if (move_window(fs, sect) != FR_OK) return 4;	/* Load boot record */
                         
                        -	if (ld_word(fs->win + BS_55AA) != 0xAA55) return 3;	/* Check boot record signature (always placed at offset 510 even if the sector size is >512) */
                        +	if (ld_word(fs->win + BS_55AA) != 0xAA55) return 3;	/* Check boot record signature (always placed here even if the sector size is >512) */
                         
                         	if (fs->win[BS_JmpBoot] == 0xE9 || (fs->win[BS_JmpBoot] == 0xEB && fs->win[BS_JmpBoot + 2] == 0x90)) {
                         		if ((ld_dword(fs->win + BS_FilSysType) & 0xFFFFFF) == 0x544146) return 0;	/* Check "FAT" string */
                        @@ -2989,29 +3040,30 @@ FRESULT find_volume (	/* FR_OK(0): successful, !=0: any error occurred */
                         	if (!_FS_READONLY && mode && (stat & STA_PROTECT)) { /* Check disk write protection if needed */
                         		return FR_WRITE_PROTECTED;
                         	}
                        -#if _MAX_SS != _MIN_SS						/* Get sector size (multiple sector size cfg only) */
                        +#if _MAX_SS != _MIN_SS					/* Get sector size (multiple sector size cfg only) */
                         	if (disk_ioctl(fs->drv, GET_SECTOR_SIZE, &SS(fs)) != RES_OK) return FR_DISK_ERR;
                         	if (SS(fs) > _MAX_SS || SS(fs) < _MIN_SS || (SS(fs) & (SS(fs) - 1))) return FR_DISK_ERR;
                         #endif
                        -	/* Find an FAT partition on the drive. Supports only generic partitioning, FDISK and SFD. */
                        +
                        +	/* Find an FAT partition on the drive. Supports only generic partitioning rules, FDISK and SFD. */
                         	bsect = 0;
                         	fmt = check_fs(fs, bsect);			/* Load sector 0 and check if it is an FAT-VBR as SFD */
                         	if (fmt == 2 || (fmt < 2 && LD2PT(vol) != 0)) {	/* Not an FAT-VBR or forced partition number */
                        -		for (i = 0; i < 4; i++) {			/* Get partition offset */
                        +		for (i = 0; i < 4; i++) {		/* Get partition offset */
                         			pt = fs->win + (MBR_Table + i * SZ_PTE);
                         			br[i] = pt[PTE_System] ? ld_dword(pt + PTE_StLba) : 0;
                         		}
                        -		i = LD2PT(vol);						/* Partition number: 0:auto, 1-4:forced */
                        +		i = LD2PT(vol);					/* Partition number: 0:auto, 1-4:forced */
                         		if (i) i--;
                        -		do {								/* Find an FAT volume */
                        +		do {							/* Find an FAT volume */
                         			bsect = br[i];
                         			fmt = bsect ? check_fs(fs, bsect) : 3;	/* Check the partition */
                        -		} while (!LD2PT(vol) && fmt >= 2 && ++i < 4);
                        +		} while (LD2PT(vol) == 0 && fmt >= 2 && ++i < 4);
                         	}
                         	if (fmt == 4) return FR_DISK_ERR;		/* An error occured in the disk I/O layer */
                         	if (fmt >= 2) return FR_NO_FILESYSTEM;	/* No FAT volume is found */
                         
                        -	/* An FAT volume is found. Following code initializes the file system object */
                        +	/* An FAT volume is found (bsect). Following code initializes the file system object */
                         
                         #if _FS_EXFAT
                         	if (fmt == 1) {
                        @@ -3022,8 +3074,9 @@ FRESULT find_volume (	/* FR_OK(0): successful, !=0: any error occurred */
                         
                         		if (ld_word(fs->win + BPB_FSVerEx) != 0x100) return FR_NO_FILESYSTEM;	/* Check exFAT revision (Must be 1.0) */
                         
                        -		if (1 << fs->win[BPB_BytsPerSecEx] != SS(fs))	/* (BPB_BytsPerSecEx must be equal to the physical sector size) */
                        +		if (1 << fs->win[BPB_BytsPerSecEx] != SS(fs)) {	/* (BPB_BytsPerSecEx must be equal to the physical sector size) */
                         			return FR_NO_FILESYSTEM;
                        +		}
                         
                         		maxlba = ld_qword(fs->win + BPB_TotSecEx) + bsect;	/* Last LBA + 1 of the volume */
                         		if (maxlba >= 0x100000000) return FR_NO_FILESYSTEM;	/* (It cannot be handled in 32-bit LBA) */
                        @@ -3062,49 +3115,49 @@ FRESULT find_volume (	/* FR_OK(0): successful, !=0: any error occurred */
                         	{
                         		if (ld_word(fs->win + BPB_BytsPerSec) != SS(fs)) return FR_NO_FILESYSTEM;	/* (BPB_BytsPerSec must be equal to the physical sector size) */
                         
                        -		fasize = ld_word(fs->win + BPB_FATSz16);			/* Number of sectors per FAT */
                        +		fasize = ld_word(fs->win + BPB_FATSz16);		/* Number of sectors per FAT */
                         		if (fasize == 0) fasize = ld_dword(fs->win + BPB_FATSz32);
                         		fs->fsize = fasize;
                         
                        -		fs->n_fats = fs->win[BPB_NumFATs];					/* Number of FATs */
                        +		fs->n_fats = fs->win[BPB_NumFATs];				/* Number of FATs */
                         		if (fs->n_fats != 1 && fs->n_fats != 2) return FR_NO_FILESYSTEM;	/* (Must be 1 or 2) */
                        -		fasize *= fs->n_fats;								/* Number of sectors for FAT area */
                        +		fasize *= fs->n_fats;							/* Number of sectors for FAT area */
                         
                        -		fs->csize = fs->win[BPB_SecPerClus];				/* Cluster size */
                        +		fs->csize = fs->win[BPB_SecPerClus];			/* Cluster size */
                         		if (fs->csize == 0 || (fs->csize & (fs->csize - 1))) return FR_NO_FILESYSTEM;	/* (Must be power of 2) */
                         
                         		fs->n_rootdir = ld_word(fs->win + BPB_RootEntCnt);	/* Number of root directory entries */
                         		if (fs->n_rootdir % (SS(fs) / SZDIRE)) return FR_NO_FILESYSTEM;	/* (Must be sector aligned) */
                         
                        -		tsect = ld_word(fs->win + BPB_TotSec16);			/* Number of sectors on the volume */
                        +		tsect = ld_word(fs->win + BPB_TotSec16);		/* Number of sectors on the volume */
                         		if (tsect == 0) tsect = ld_dword(fs->win + BPB_TotSec32);
                         
                        -		nrsv = ld_word(fs->win + BPB_RsvdSecCnt);			/* Number of reserved sectors */
                        -		if (nrsv == 0) return FR_NO_FILESYSTEM;				/* (Must not be 0) */
                        +		nrsv = ld_word(fs->win + BPB_RsvdSecCnt);		/* Number of reserved sectors */
                        +		if (nrsv == 0) return FR_NO_FILESYSTEM;			/* (Must not be 0) */
                         
                         		/* Determine the FAT sub type */
                         		sysect = nrsv + fasize + fs->n_rootdir / (SS(fs) / SZDIRE);	/* RSV + FAT + DIR */
                        -		if (tsect < sysect) return FR_NO_FILESYSTEM;		/* (Invalid volume size) */
                        -		nclst = (tsect - sysect) / fs->csize;				/* Number of clusters */
                        -		if (nclst == 0) return FR_NO_FILESYSTEM;			/* (Invalid volume size) */
                        +		if (tsect < sysect) return FR_NO_FILESYSTEM;	/* (Invalid volume size) */
                        +		nclst = (tsect - sysect) / fs->csize;			/* Number of clusters */
                        +		if (nclst == 0) return FR_NO_FILESYSTEM;		/* (Invalid volume size) */
                         		fmt = FS_FAT32;
                         		if (nclst <= MAX_FAT16) fmt = FS_FAT16;
                         		if (nclst <= MAX_FAT12) fmt = FS_FAT12;
                         
                         		/* Boundaries and Limits */
                        -		fs->n_fatent = nclst + 2;							/* Number of FAT entries */
                        -		fs->volbase = bsect;								/* Volume start sector */
                        -		fs->fatbase = bsect + nrsv; 						/* FAT start sector */
                        -		fs->database = bsect + sysect;						/* Data start sector */
                        +		fs->n_fatent = nclst + 2;						/* Number of FAT entries */
                        +		fs->volbase = bsect;							/* Volume start sector */
                        +		fs->fatbase = bsect + nrsv; 					/* FAT start sector */
                        +		fs->database = bsect + sysect;					/* Data start sector */
                         		if (fmt == FS_FAT32) {
                         			if (ld_word(fs->win + BPB_FSVer32) != 0) return FR_NO_FILESYSTEM;	/* (Must be FAT32 revision 0.0) */
                        -			if (fs->n_rootdir) return FR_NO_FILESYSTEM;		/* (BPB_RootEntCnt must be 0) */
                        +			if (fs->n_rootdir) return FR_NO_FILESYSTEM;	/* (BPB_RootEntCnt must be 0) */
                         			fs->dirbase = ld_dword(fs->win + BPB_RootClus32);	/* Root directory start cluster */
                        -			szbfat = fs->n_fatent * 4;						/* (Needed FAT size) */
                        +			szbfat = fs->n_fatent * 4;					/* (Needed FAT size) */
                         		} else {
                         			if (fs->n_rootdir == 0)	return FR_NO_FILESYSTEM;/* (BPB_RootEntCnt must not be 0) */
                        -			fs->dirbase = fs->fatbase + fasize;				/* Root directory start sector */
                        -			szbfat = (fmt == FS_FAT16) ?					/* (Needed FAT size) */
                        +			fs->dirbase = fs->fatbase + fasize;			/* Root directory start sector */
                        +			szbfat = (fmt == FS_FAT16) ?				/* (Needed FAT size) */
                         				fs->n_fatent * 2 : fs->n_fatent * 3 / 2 + (fs->n_fatent & 1);
                         		}
                         		if (fs->fsize < (szbfat + (SS(fs) - 1)) / SS(fs)) return FR_NO_FILESYSTEM;	/* (BPB_FATSz must not be less than the size needed) */
                        @@ -3135,18 +3188,18 @@ FRESULT find_volume (	/* FR_OK(0): successful, !=0: any error occurred */
                         #endif	/* !_FS_READONLY */
                         	}
                         
                        -	fs->fs_type = fmt;	/* FAT sub-type */
                        -	fs->id = ++Fsid;	/* File system mount ID */
                        +	fs->fs_type = fmt;		/* FAT sub-type */
                        +	fs->id = ++Fsid;		/* File system mount ID */
                         #if _USE_LFN == 1
                         	fs->lfnbuf = LfnBuf;	/* Static LFN working buffer */
                         #if _FS_EXFAT
                        -	fs->dirbuf = DirBuf;	/* Static directory block working buuffer */
                        +	fs->dirbuf = DirBuf;	/* Static directory block scratchpad buuffer */
                         #endif
                         #endif
                         #if _FS_RPATH != 0
                        -	fs->cdir = 0;		/* Initialize current directory */
                        +	fs->cdir = 0;			/* Initialize current directory */
                         #endif
                        -#if _FS_LOCK != 0		/* Clear file lock semaphores */
                        +#if _FS_LOCK != 0			/* Clear file lock semaphores */
                         	clear_lock(fs);
                         #endif
                         	return FR_OK;
                        @@ -3167,14 +3220,13 @@ FRESULT validate (	/* Returns FR_OK or FR_INVALID_OBJECT */
                         {
                         	FRESULT res;
                         
                        -
                         	if (!obj || !obj->fs || !obj->fs->fs_type || obj->fs->id != obj->id || (disk_status(obj->fs->drv) & STA_NOINIT)) {
                        -		*fs = 0;				/* The object is invalid */
                        -		res = FR_INVALID_OBJECT;
                        +		*fs = 0;
                        +		res = FR_INVALID_OBJECT;	/* The object is invalid */
                         	} else {
                         		*fs = obj->fs;			/* Owner file sytem object */
                         		ENTER_FF(obj->fs);		/* Lock file system */
                        -		res = FR_OK;
                        +		res = FR_OK;			/* Valid object */
                         	}
                         	return res;
                         }
                        @@ -3281,12 +3333,13 @@ FRESULT f_open (
                         		/* Create or Open a file */
                         		if (mode & (FA_CREATE_ALWAYS | FA_OPEN_ALWAYS | FA_CREATE_NEW)) {
                         			if (res != FR_OK) {					/* No file, create new */
                        -				if (res == FR_NO_FILE)			/* There is no file to open, create a new entry */
                        +				if (res == FR_NO_FILE) {		/* There is no file to open, create a new entry */
                         #if _FS_LOCK != 0
                         					res = enq_lock() ? dir_register(&dj) : FR_TOO_MANY_OPEN_FILES;
                         #else
                         					res = dir_register(&dj);
                         #endif
                        +				}
                         				mode |= FA_CREATE_ALWAYS;		/* File is created */
                         			}
                         			else {								/* Any object is already existing */
                        @@ -3305,6 +3358,7 @@ FRESULT f_open (
                         					fp->obj.sclust = ld_dword(fs->dirbuf + XDIR_FstClus);
                         					fp->obj.objsize = ld_qword(fs->dirbuf + XDIR_FileSize);
                         					fp->obj.stat = fs->dirbuf[XDIR_GenFlags] & 2;
                        +					fp->obj.n_frag = 0;
                         					/* Initialize directory entry block */
                         					st_dword(fs->dirbuf + XDIR_CrtTime, dw);	/* Set created time */
                         					fs->dirbuf[XDIR_CrtTime10] = 0;
                        @@ -3379,16 +3433,16 @@ FRESULT f_open (
                         		if (res == FR_OK) {
                         #if _FS_EXFAT
                         			if (fs->fs_type == FS_EXFAT) {
                        -				fp->obj.sclust = ld_dword(fs->dirbuf + XDIR_FstClus);		/* Get allocation info */
                        -				fp->obj.objsize = ld_qword(fs->dirbuf + XDIR_FileSize);
                        -				fp->obj.stat = fs->dirbuf[XDIR_GenFlags] & 2;
                        -				fp->obj.c_scl = dj.obj.sclust;
                        +				fp->obj.c_scl = dj.obj.sclust;							/* Get containing directory info */
                         				fp->obj.c_size = ((DWORD)dj.obj.objsize & 0xFFFFFF00) | dj.obj.stat;
                         				fp->obj.c_ofs = dj.blk_ofs;
                        +				fp->obj.sclust = ld_dword(fs->dirbuf + XDIR_FstClus);	/* Get object allocation info */
                        +				fp->obj.objsize = ld_qword(fs->dirbuf + XDIR_FileSize);
                        +				fp->obj.stat = fs->dirbuf[XDIR_GenFlags] & 2;
                         			} else
                         #endif
                         			{
                        -				fp->obj.sclust = ld_clust(fs, dj.dir);				/* Get allocation info */
                        +				fp->obj.sclust = ld_clust(fs, dj.dir);					/* Get object allocation info */
                         				fp->obj.objsize = ld_dword(dj.dir + DIR_FileSize);
                         			}
                         #if _USE_FASTSEEK
                        @@ -3672,8 +3726,10 @@ FRESULT f_sync (
                         	FATFS *fs;
                         	DWORD tm;
                         	BYTE *dir;
                        +#if _FS_EXFAT
                        +	DIR dj;
                         	DEF_NAMBUF
                        -
                        +#endif
                         
                         	res = validate(&fp->obj, &fs);	/* Check validity of the file object */
                         	if (res == FR_OK) {
                        @@ -3688,10 +3744,11 @@ FRESULT f_sync (
                         			tm = GET_FATTIME();				/* Modified time */
                         #if _FS_EXFAT
                         			if (fs->fs_type == FS_EXFAT) {
                        -				res = fill_fat_chain(&fp->obj);	/* Create FAT chain if needed */
                        +				res = fill_first_frag(&fp->obj);	/* Fill first fragment on the FAT if needed */
                        +				if (res == FR_OK) {
                        +					res = fill_last_frag(&fp->obj, fp->clust, 0xFFFFFFFF);	/* Fill last fragment on the FAT if needed */
                        +				}
                         				if (res == FR_OK) {
                        -					DIR dj;
                        -
                         					INIT_NAMBUF(fs);
                         					res = load_obj_dir(&dj, &fp->obj);	/* Load directory entry block */
                         					if (res == FR_OK) {
                        @@ -3944,7 +4001,14 @@ FRESULT f_lseek (
                         #endif
                         
                         	res = validate(&fp->obj, &fs);		/* Check validity of the file object */
                        -	if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res);	/* Check validity */
                        +	if (res == FR_OK) res = (FRESULT)fp->err;
                        +#if _FS_EXFAT && !_FS_READONLY
                        +	if (res == FR_OK && fs->fs_type == FS_EXFAT) {
                        +		res = fill_last_frag(&fp->obj, fp->clust, 0xFFFFFFFF);	/* Fill last fragment on the FAT if needed */
                        +	}
                        +#endif
                        +	if (res != FR_OK) LEAVE_FF(fs, res);
                        +
                         #if _USE_FASTSEEK
                         	if (fp->cltbl) {	/* Fast seek */
                         		if (ofs == CREATE_LINKMAP) {	/* Create CLMT */
                        @@ -4109,16 +4173,16 @@ FRESULT f_opendir (
                         				if (obj->attr & AM_DIR) {		/* This object is a sub-directory */
                         #if _FS_EXFAT
                         					if (fs->fs_type == FS_EXFAT) {
                        -						obj->c_scl = obj->sclust;	/* Save containing directory inforamation */
                        +						obj->c_scl = obj->sclust;							/* Get containing directory inforamation */
                         						obj->c_size = ((DWORD)obj->objsize & 0xFFFFFF00) | obj->stat;
                         						obj->c_ofs = dp->blk_ofs;
                        -						obj->sclust = ld_dword(fs->dirbuf + XDIR_FstClus);	/* Get object location and status */
                        +						obj->sclust = ld_dword(fs->dirbuf + XDIR_FstClus);	/* Get object allocation info */
                         						obj->objsize = ld_qword(fs->dirbuf + XDIR_FileSize);
                         						obj->stat = fs->dirbuf[XDIR_GenFlags] & 2;
                         					} else
                         #endif
                         					{
                        -						obj->sclust = ld_clust(fs, dp->dir);	/* Get object location */
                        +						obj->sclust = ld_clust(fs, dp->dir);	/* Get object allocation info */
                         					}
                         				} else {						/* This object is a file */
                         					res = FR_NO_PATH;
                        @@ -4410,7 +4474,7 @@ FRESULT f_truncate (
                         	if (res != FR_OK || (res = (FRESULT)fp->err) != FR_OK) LEAVE_FF(fs, res);
                         	if (!(fp->flag & FA_WRITE)) LEAVE_FF(fs, FR_DENIED);	/* Check access mode */
                         
                        -	if (fp->obj.objsize > fp->fptr) {
                        +	if (fp->fptr < fp->obj.objsize) {	/* Process when fptr is not on the eof */
                         		if (fp->fptr == 0) {	/* When set file size to zero, remove entire cluster chain */
                         			res = remove_chain(&fp->obj, fp->obj.sclust, 0);
                         			fp->obj.sclust = 0;
                        @@ -4493,7 +4557,7 @@ FRESULT f_unlink (
                         				{
                         					dclst = ld_clust(fs, dj.dir);
                         				}
                        -				if (dj.obj.attr & AM_DIR) {			/* Is it a sub-directory ? */
                        +				if (dj.obj.attr & AM_DIR) {			/* Is it a sub-directory? */
                         #if _FS_RPATH != 0
                         					if (dclst == fs->cdir) {		 		/* Is it the current directory? */
                         						res = FR_DENIED;
                        @@ -4597,7 +4661,9 @@ FRESULT f_mkdir (
                         					mem_set(dir, 0, SS(fs));
                         				}
                         			}
                        -			if (res == FR_OK) res = dir_register(&dj);	/* Register the object to the directoy */
                        +			if (res == FR_OK) {
                        +				res = dir_register(&dj);	/* Register the object to the directoy */
                        +			}
                         			if (res == FR_OK) {
                         #if _FS_EXFAT
                         				if (fs->fs_type == FS_EXFAT) {	/* Initialize directory entry block */
                        @@ -4617,7 +4683,9 @@ FRESULT f_mkdir (
                         					dir[DIR_Attr] = AM_DIR;				/* Attribute */
                         					fs->wflag = 1;
                         				}
                        -				if (res == FR_OK) res = sync_fs(fs);
                        +				if (res == FR_OK) {
                        +					res = sync_fs(fs);
                        +				}
                         			} else {
                         				remove_chain(&dj.obj, dcl, 0);		/* Could not register, remove cluster chain */
                         			}
                        @@ -4648,7 +4716,7 @@ FRESULT f_rename (
                         	DEF_NAMBUF
                         
                         
                        -	get_ldnumber(&path_new);						/* Ignore drive number of new name */
                        +	get_ldnumber(&path_new);						/* Snip drive number of new name off */
                         	res = find_volume(&path_old, &fs, FA_WRITE);	/* Get logical drive of the old object */
                         	if (res == FR_OK) {
                         		djo.obj.fs = fs;
                        @@ -4656,7 +4724,9 @@ FRESULT f_rename (
                         		res = follow_path(&djo, path_old);		/* Check old object */
                         		if (res == FR_OK && (djo.fn[NSFLAG] & (NS_DOT | NS_NONAME))) res = FR_INVALID_NAME;	/* Check validity of name */
                         #if _FS_LOCK != 0
                        -		if (res == FR_OK) res = chk_lock(&djo, 2);
                        +		if (res == FR_OK) {
                        +			res = chk_lock(&djo, 2);
                        +		}
                         #endif
                         		if (res == FR_OK) {						/* Object to be renamed is found */
                         #if _FS_EXFAT
                        @@ -4678,7 +4748,7 @@ FRESULT f_rename (
                         						mem_cpy(fs->dirbuf, buf, SZDIRE * 2);
                         						fs->dirbuf[XDIR_NumSec] = nf; fs->dirbuf[XDIR_NumName] = nn;
                         						st_word(fs->dirbuf + XDIR_NameHash, nh);
                        -/* Start of critical section where any interruption can cause a cross-link */
                        +/* Start of critical section where an interruption can cause a cross-link */
                         						res = store_xdir(&djn);
                         					}
                         				}
                        @@ -4703,7 +4773,7 @@ FRESULT f_rename (
                         							if (!dw) {
                         								res = FR_INT_ERR;
                         							} else {
                        -/* Start of critical section where any interruption can cause a cross-link */
                        +/* Start of critical section where an interruption can cause a cross-link */
                         								res = move_window(fs, dw);
                         								dir = fs->win + SZDIRE * 1;	/* Ptr to .. entry */
                         								if (res == FR_OK && dir[1] == '.') {
                        @@ -4721,7 +4791,7 @@ FRESULT f_rename (
                         					res = sync_fs(fs);
                         				}
                         			}
                        -/* End of critical section */
                        +/* End of the critical section */
                         		}
                         		FREE_NAMBUF();
                         	}
                        @@ -4771,7 +4841,9 @@ FRESULT f_chmod (
                         				dj.dir[DIR_Attr] = (attr & mask) | (dj.dir[DIR_Attr] & (BYTE)~mask);	/* Apply attribute change */
                         				fs->wflag = 1;
                         			}
                        -			if (res == FR_OK) res = sync_fs(fs);
                        +			if (res == FR_OK) {
                        +				res = sync_fs(fs);
                        +			}
                         		}
                         		FREE_NAMBUF();
                         	}
                        @@ -4814,7 +4886,9 @@ FRESULT f_utime (
                         				st_dword(dj.dir + DIR_ModTime, (DWORD)fno->fdate << 16 | fno->ftime);
                         				fs->wflag = 1;
                         			}
                        -			if (res == FR_OK) res = sync_fs(fs);
                        +			if (res == FR_OK) {
                        +				res = sync_fs(fs);
                        +			}
                         		}
                         		FREE_NAMBUF();
                         	}
                        @@ -4902,9 +4976,14 @@ FRESULT f_getlabel (
                         		res = move_window(fs, fs->volbase);
                         		if (res == FR_OK) {
                         			switch (fs->fs_type) {
                        -			case FS_EXFAT: di = BPB_VolIDEx; break;
                        -			case FS_FAT32: di = BS_VolID32; break;
                        -			default:       di = BS_VolID;
                        +			case FS_EXFAT:
                        +				di = BPB_VolIDEx; break;
                        +
                        +			case FS_FAT32:
                        +				di = BS_VolID32; break;
                        +
                        +			default:
                        +				di = BS_VolID;
                         			}
                         			*vsn = ld_dword(fs->win + di);
                         		}
                        @@ -5074,11 +5153,11 @@ FRESULT f_expand (
                         		scl = find_bitmap(fs, stcl, tcl);			/* Find a contiguous cluster block */
                         		if (scl == 0) res = FR_DENIED;				/* No contiguous cluster block was found */
                         		if (scl == 0xFFFFFFFF) res = FR_DISK_ERR;
                        -		if (res == FR_OK) {
                        -			if (opt) {
                        +		if (res == FR_OK) {	/* A contiguous free area is found */
                        +			if (opt) {		/* Allocate it now */
                         				res = change_bitmap(fs, scl, tcl, 1);	/* Mark the cluster block 'in use' */
                         				lclst = scl + tcl - 1;
                        -			} else {
                        +			} else {		/* Set it as suggested point for next allocation */
                         				lclst = scl - 1;
                         			}
                         		}
                        @@ -5098,14 +5177,14 @@ FRESULT f_expand (
                         			}
                         			if (clst == stcl) { res = FR_DENIED; break; }	/* No contiguous cluster? */
                         		}
                        -		if (res == FR_OK) {
                        -			if (opt) {
                        +		if (res == FR_OK) {	/* A contiguous free area is found */
                        +			if (opt) {		/* Allocate it now */
                         				for (clst = scl, n = tcl; n; clst++, n--) {	/* Create a cluster chain on the FAT */
                         					res = put_fat(fs, clst, (n == 1) ? 0xFFFFFFFF : clst + 1);
                         					if (res != FR_OK) break;
                         					lclst = clst;
                         				}
                        -			} else {
                        +			} else {		/* Set it as suggested point for next allocation */
                         				lclst = scl - 1;
                         			}
                         		}
                        @@ -5113,12 +5192,12 @@ FRESULT f_expand (
                         
                         	if (res == FR_OK) {
                         		fs->last_clst = lclst;		/* Set suggested start cluster to start next */
                        -		if (opt) {
                        +		if (opt) {	/* Is it allocated now? */
                         			fp->obj.sclust = scl;		/* Update object allocation information */
                         			fp->obj.objsize = fsz;
                         			if (_FS_EXFAT) fp->obj.stat = 2;	/* Set status 'contiguous chain' */
                         			fp->flag |= FA_MODIFIED;
                        -			if (fs->free_clst  < fs->n_fatent - 2) {	/* Update FSINFO */
                        +			if (fs->free_clst <= fs->n_fatent - 2) {	/* Update FSINFO */
                         				fs->free_clst -= tcl;
                         				fs->fsi_flag |= 1;
                         			}
                        @@ -5205,13 +5284,13 @@ FRESULT f_forward (
                         
                         #if _USE_MKFS && !_FS_READONLY
                         /*-----------------------------------------------------------------------*/
                        -/* Create FAT file system on the logical drive                           */
                        +/* Create an FAT/exFAT volume                                            */
                         /*-----------------------------------------------------------------------*/
                         
                         FRESULT f_mkfs (
                         	const TCHAR* path,	/* Logical drive number */
                         	BYTE opt,			/* Format option */
                        -	DWORD au,			/* Size of allocation unit [byte] */
                        +	DWORD au,			/* Size of allocation unit (cluster) [byte] */
                         	void* work,			/* Pointer to working buffer */
                         	UINT len			/* Size of working buffer */
                         )
                        @@ -5236,7 +5315,7 @@ FRESULT f_mkfs (
                         	/* Check mounted drive and clear work area */
                         	vol = get_ldnumber(&path);					/* Get target logical drive */
                         	if (vol < 0) return FR_INVALID_DRIVE;
                        -	if (FatFs[vol]) FatFs[vol]->fs_type = 0;	/* Clear mounted volume */
                        +	if (FatFs[vol]) FatFs[vol]->fs_type = 0;	/* Clear the volume */
                         	pdrv = LD2PD(vol);	/* Physical drive */
                         	part = LD2PT(vol);	/* Partition (0:create as new, 1-4:get from partition table) */
                         
                        @@ -5245,7 +5324,7 @@ FRESULT f_mkfs (
                         	if (stat & STA_NOINIT) return FR_NOT_READY;
                         	if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
                         	if (disk_ioctl(pdrv, GET_BLOCK_SIZE, &sz_blk) != RES_OK || !sz_blk || sz_blk > 32768 || (sz_blk & (sz_blk - 1))) sz_blk = 1;	/* Erase block to align data area */
                        -#if _MAX_SS != _MIN_SS		/* Get sector size of the medium */
                        +#if _MAX_SS != _MIN_SS		/* Get sector size of the medium if variable sector size cfg. */
                         	if (disk_ioctl(pdrv, GET_SECTOR_SIZE, &ss) != RES_OK) return FR_DISK_ERR;
                         	if (ss > _MAX_SS || ss < _MIN_SS || (ss & (ss - 1))) return FR_DISK_ERR;
                         #else
                        @@ -5304,7 +5383,7 @@ FRESULT f_mkfs (
                         
                         		if (sz_vol < 0x1000) return FR_MKFS_ABORTED;	/* Too small volume? */
                         #if _USE_TRIM
                        -		tbl[0] = b_vol; tbl[1] = b_vol + sz_vol - 1;	/* Inform the device the volume area can be erased */
                        +		tbl[0] = b_vol; tbl[1] = b_vol + sz_vol - 1;	/* Inform the device the volume area may be erased */
                         		disk_ioctl(pdrv, CTRL_TRIM, tbl);
                         #endif
                         		/* Determine FAT location, data location and number of clusters */
                        @@ -5340,11 +5419,12 @@ FRESULT f_mkfs (
                         					ch = 0xFFFF; st = 2; break;	/* Compress the no-case block if run is >= 128 */
                         				}
                         				st = 1;			/* Do not compress short run */
                        -				/* continue */
                        +				/* go to next case */
                         			case 1:
                         				ch = si++;		/* Fill the short run */
                         				if (--j == 0) st = 0;
                         				break;
                        +
                         			default:
                         				ch = (WCHAR)j; si += j;	/* Number of chars to skip */
                         				st = 0;
                        @@ -5626,14 +5706,14 @@ FRESULT f_mkfs (
                         		}
                         	}
                         
                        -	if (_MULTI_PARTITION && part != 0) {
                        +	/* Update partition information */
                        +	if (_MULTI_PARTITION && part != 0) {	/* Created in the existing partition */
                         		/* Update system ID in the partition table */
                         		if (disk_read(pdrv, buf, 0, 1) != RES_OK) return FR_DISK_ERR;	/* Read the MBR */
                        -		buf[MBR_Table + (part - 1) * SZ_PTE + PTE_System] = sys;		/* Set system type */
                        +		buf[MBR_Table + (part - 1) * SZ_PTE + PTE_System] = sys;		/* Set system ID */
                         		if (disk_write(pdrv, buf, 0, 1) != RES_OK) return FR_DISK_ERR;	/* Write it back to the MBR */
                        -	} else {
                        -		if (!(opt & FM_SFD)) {
                        -			/* Create partition table in FDISK format */
                        +	} else {								/* Created as a new single partition */
                        +		if (!(opt & FM_SFD)) {	/* Create partition table if in FDISK format */
                         			mem_set(buf, 0, ss);
                         			st_word(buf + BS_55AA, 0xAA55);		/* MBR signature */
                         			pte = buf + MBR_Table;				/* Create partition table for single partition in the drive */
                        @@ -5642,7 +5722,7 @@ FRESULT f_mkfs (
                         			pte[PTE_StSec] = 1;					/* Start sector */
                         			pte[PTE_StCyl] = 0;					/* Start cylinder */
                         			pte[PTE_System] = sys;				/* System type */
                        -			n = (b_vol + sz_vol) / (63 * 255);	/* (End CHS is incorrect) */
                        +			n = (b_vol + sz_vol) / (63 * 255);	/* (End CHS may be invalid) */
                         			pte[PTE_EdHead] = 254;				/* End head */
                         			pte[PTE_EdSec] = (BYTE)(n >> 2 | 63);	/* End sector */
                         			pte[PTE_EdCyl] = (BYTE)n;			/* End cylinder */
                        @@ -5681,7 +5761,7 @@ FRESULT f_fdisk (
                         	if (stat & STA_PROTECT) return FR_WRITE_PROTECTED;
                         	if (disk_ioctl(pdrv, GET_SECTOR_COUNT, &sz_disk)) return FR_DISK_ERR;
                         
                        -	/* Determine the CHS without any care of the drive geometry */
                        +	/* Determine the CHS without any consideration of the drive geometry */
                         	for (n = 16; n < 256 && sz_disk / n / 63 > 1024; n *= 2) ;
                         	if (n == 256) n--;
                         	e_hd = n - 1;
                        @@ -5692,7 +5772,7 @@ FRESULT f_fdisk (
                         	mem_set(buf, 0, _MAX_SS);
                         	p = buf + MBR_Table; b_cyl = 0;
                         	for (i = 0; i < 4; i++, p += SZ_PTE) {
                        -		p_cyl = (szt[i] <= 100U) ? (DWORD)tot_cyl * szt[i] / 100 : szt[i] / sz_cyl;
                        +		p_cyl = (szt[i] <= 100U) ? (DWORD)tot_cyl * szt[i] / 100 : szt[i] / sz_cyl;	/* Number of cylinders */
                         		if (!p_cyl) continue;
                         		s_part = (DWORD)sz_cyl * b_cyl;
                         		sz_part = (DWORD)sz_cyl * p_cyl;
                        @@ -5702,19 +5782,19 @@ FRESULT f_fdisk (
                         		} else {
                         			s_hd = 0;
                         		}
                        -		e_cyl = b_cyl + p_cyl - 1;
                        +		e_cyl = b_cyl + p_cyl - 1;	/* End cylinder */
                         		if (e_cyl >= tot_cyl) return FR_INVALID_PARAMETER;
                         
                         		/* Set partition table */
                         		p[1] = s_hd;						/* Start head */
                         		p[2] = (BYTE)((b_cyl >> 2) + 1);	/* Start sector */
                         		p[3] = (BYTE)b_cyl;					/* Start cylinder */
                        -		p[4] = 0x06;						/* System type (temporary setting) */
                        +		p[4] = 0x07;						/* System type (temporary setting) */
                         		p[5] = e_hd;						/* End head */
                         		p[6] = (BYTE)((e_cyl >> 2) + 63);	/* End sector */
                         		p[7] = (BYTE)e_cyl;					/* End cylinder */
                         		st_dword(p + 8, s_part);			/* Start sector in LBA */
                        -		st_dword(p + 12, sz_part);			/* Partition size */
                        +		st_dword(p + 12, sz_part);			/* Number of sectors */
                         
                         		/* Next partition */
                         		b_cyl += p_cyl;
                        @@ -5756,17 +5836,17 @@ TCHAR* f_gets (
                         		c = s[0];
                         		if (c >= 0x80) {
                         			if (c < 0xC0) continue;	/* Skip stray trailer */
                        -			if (c < 0xE0) {			/* Two-byte sequence */
                        +			if (c < 0xE0) {			/* Two-byte sequence (0x80-0x7FF) */
                         				f_read(fp, s, 1, &rc);
                         				if (rc != 1) break;
                         				c = (c & 0x1F) << 6 | (s[0] & 0x3F);
                        -				if (c < 0x80) c = '?';
                        +				if (c < 0x80) c = '?';	/* Reject invalid code range */
                         			} else {
                        -				if (c < 0xF0) {		/* Three-byte sequence */
                        +				if (c < 0xF0) {		/* Three-byte sequence (0x800-0xFFFF) */
                         					f_read(fp, s, 2, &rc);
                         					if (rc != 2) break;
                         					c = c << 12 | (s[0] & 0x3F) << 6 | (s[1] & 0x3F);
                        -					if (c < 0x800) c = '?';
                        +					if (c < 0x800) c = '?';	/* Reject invalid code range */
                         				} else {			/* Reject four-byte sequence */
                         					c = '?';
                         				}
                        @@ -5998,17 +6078,23 @@ int f_printf (
                         			while (*p) putc_bfd(&pb, *p++);
                         			while (j++ < w) putc_bfd(&pb, ' ');
                         			continue;
                        +
                         		case 'C' :					/* Character */
                         			putc_bfd(&pb, (TCHAR)va_arg(arp, int)); continue;
                        +
                         		case 'B' :					/* Binary */
                         			r = 2; break;
                        +
                         		case 'O' :					/* Octal */
                         			r = 8; break;
                        +
                         		case 'D' :					/* Signed decimal */
                         		case 'U' :					/* Unsigned decimal */
                         			r = 10; break;
                        +
                         		case 'X' :					/* Hexdecimal */
                         			r = 16; break;
                        +
                         		default:					/* Unknown type (pass-through) */
                         			putc_bfd(&pb, c); continue;
                         		}
                        @@ -6028,7 +6114,9 @@ int f_printf (
                         		if (f & 8) str[i++] = '-';
                         		j = i; d = (f & 1) ? '0' : ' ';
                         		while (!(f & 2) && j++ < w) putc_bfd(&pb, d);
                        -		do putc_bfd(&pb, str[--i]); while (i);
                        +		do {
                        +			putc_bfd(&pb, str[--i]);
                        +		} while (i);
                         		while (j++ < w) putc_bfd(&pb, d);
                         	}
                         
                        diff --git a/firmware/chibios-portapack/ext/fatfs/src/ff.h b/firmware/chibios-portapack/ext/fatfs/src/ff.h
                        index 981a8863..f9025198 100644
                        --- a/firmware/chibios-portapack/ext/fatfs/src/ff.h
                        +++ b/firmware/chibios-portapack/ext/fatfs/src/ff.h
                        @@ -1,8 +1,8 @@
                         /*----------------------------------------------------------------------------/
                        -/  FatFs - Generic FAT file system module  R0.12b                             /
                        +/  FatFs - Generic FAT file system module  R0.12c                             /
                         /-----------------------------------------------------------------------------/
                         /
                        -/ Copyright (C) 2016, ChaN, all right reserved.
                        +/ Copyright (C) 2017, ChaN, all right reserved.
                         /
                         / FatFs module is an open source software. Redistribution and use of FatFs in
                         / source and binary forms, with or without modification, are permitted provided
                        @@ -19,7 +19,7 @@
                         
                         
                         #ifndef _FATFS
                        -#define _FATFS	68020	/* Revision ID */
                        +#define _FATFS	68300	/* Revision ID */
                         
                         #ifdef __cplusplus
                         extern "C" {
                        @@ -42,13 +42,6 @@ typedef struct {
                         	BYTE pt;	/* Partition: 0:Auto detect, 1-4:Forced partition) */
                         } PARTITION;
                         extern PARTITION VolToPart[];	/* Volume - Partition resolution table */
                        -#define LD2PD(vol) (VolToPart[vol].pd)	/* Get physical drive number */
                        -#define LD2PT(vol) (VolToPart[vol].pt)	/* Get partition index */
                        -
                        -#else							/* Single partition configuration */
                        -#define LD2PD(vol) (BYTE)(vol)	/* Each logical drive is bound to the same physical drive number */
                        -#define LD2PT(vol) 0			/* Find first valid partition or in SFD */
                        -
                         #endif
                         
                         
                        @@ -140,14 +133,15 @@ typedef struct {
                         	FATFS*	fs;			/* Pointer to the owner file system object */
                         	WORD	id;			/* Owner file system mount ID */
                         	BYTE	attr;		/* Object attribute */
                        -	BYTE	stat;		/* Object chain status (b1-0: =0:not contiguous, =2:contiguous (no data on FAT), =3:got flagmented, b2:sub-directory stretched) */
                        +	BYTE	stat;		/* Object chain status (b1-0: =0:not contiguous, =2:contiguous (no data on FAT), =3:flagmented in this session, b2:sub-directory stretched) */
                         	DWORD	sclust;		/* Object start cluster (0:no cluster or root directory) */
                         	FSIZE_t	objsize;	/* Object size (valid when sclust != 0) */
                         #if _FS_EXFAT
                        -	DWORD	n_cont;		/* Size of coutiguous part, clusters - 1 (valid when stat == 3) */
                        +	DWORD	n_cont;		/* Size of first fragment, clusters - 1 (valid when stat == 3) */
                        +	DWORD	n_frag;		/* Size of last fragment needs to be written (valid when not zero) */
                         	DWORD	c_scl;		/* Containing directory start cluster (valid when sclust != 0) */
                         	DWORD	c_size;		/* b31-b8:Size of containing directory, b7-b0: Chain status (valid when c_scl != 0) */
                        -	DWORD	c_ofs;		/* Offset in the containing directory (valid when sclust != 0) */
                        +	DWORD	c_ofs;		/* Offset in the containing directory (valid when sclust != 0 and non-directory object) */
                         #endif
                         #if _FS_LOCK != 0
                         	UINT	lockid;		/* File lock ID origin from 1 (index of file semaphore table Files[]) */
                        @@ -163,7 +157,7 @@ typedef struct {
                         	BYTE	flag;			/* File status flags */
                         	BYTE	err;			/* Abort flag (error code) */
                         	FSIZE_t	fptr;			/* File read/write pointer (Zeroed on file open) */
                        -	DWORD	clust;			/* Current cluster of fpter (invalid when fprt is 0) */
                        +	DWORD	clust;			/* Current cluster of fpter (invalid when fptr is 0) */
                         	DWORD	sect;			/* Sector number appearing in buf[] (0:invalid) */
                         #if !_FS_READONLY
                         	DWORD	dir_sect;		/* Sector number containing the directory entry */
                        @@ -185,7 +179,7 @@ typedef struct {
                         	_FDID	obj;			/* Object identifier */
                         	DWORD	dptr;			/* Current read/write offset */
                         	DWORD	clust;			/* Current cluster */
                        -	DWORD	sect;			/* Current sector */
                        +	DWORD	sect;			/* Current sector (0:Read operation has terminated) */
                         	BYTE*	dir;			/* Pointer to the directory item in the win[] */
                         	BYTE	fn[12];			/* SFN (in/out) {body[8],ext[3],status[1]} */
                         #if _USE_LFN != 0
                        @@ -285,6 +279,7 @@ TCHAR* f_gets (TCHAR* buff, int len, FIL* fp);						/* Get a string from the fil
                         #define f_size(fp) ((fp)->obj.objsize)
                         #define f_rewind(fp) f_lseek((fp), 0)
                         #define f_rewinddir(dp) f_readdir((dp), 0)
                        +#define f_rmdir(path) f_unlink(path)
                         
                         #ifndef EOF
                         #define EOF (-1)
                        diff --git a/firmware/chibios-portapack/ext/fatfs/src/ffconf_template.h b/firmware/chibios-portapack/ext/fatfs/src/ffconf_template.h
                        deleted file mode 100644
                        index 8db3d7cb..00000000
                        --- a/firmware/chibios-portapack/ext/fatfs/src/ffconf_template.h
                        +++ /dev/null
                        @@ -1,265 +0,0 @@
                        -/*---------------------------------------------------------------------------/
                        -/  FatFs - FAT file system module configuration file
                        -/---------------------------------------------------------------------------*/
                        -
                        -#define _FFCONF 80186	/* Revision ID */
                        -
                        -/*---------------------------------------------------------------------------/
                        -/ Function Configurations
                        -/---------------------------------------------------------------------------*/
                        -
                        -#define _FS_READONLY	0
                        -/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
                        -/  Read-only configuration removes writing API functions, f_write(), f_sync(),
                        -/  f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
                        -/  and optional writing functions as well. */
                        -
                        -
                        -#define _FS_MINIMIZE	0
                        -/* This option defines minimization level to remove some basic API functions.
                        -/
                        -/   0: All basic functions are enabled.
                        -/   1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
                        -/      are removed.
                        -/   2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
                        -/   3: f_lseek() function is removed in addition to 2. */
                        -
                        -
                        -#define	_USE_STRFUNC	0
                        -/* This option switches string functions, f_gets(), f_putc(), f_puts() and
                        -/  f_printf().
                        -/
                        -/  0: Disable string functions.
                        -/  1: Enable without LF-CRLF conversion.
                        -/  2: Enable with LF-CRLF conversion. */
                        -
                        -
                        -#define _USE_FIND		0
                        -/* This option switches filtered directory read functions, f_findfirst() and
                        -/  f_findnext(). (0:Disable, 1:Enable 2:Enable with matching altname[] too) */
                        -
                        -
                        -#define	_USE_MKFS		0
                        -/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
                        -
                        -
                        -#define	_USE_FASTSEEK	0
                        -/* This option switches fast seek function. (0:Disable or 1:Enable) */
                        -
                        -
                        -#define	_USE_EXPAND		0
                        -/* This option switches f_expand function. (0:Disable or 1:Enable) */
                        -
                        -
                        -#define _USE_CHMOD		0
                        -/* This option switches attribute manipulation functions, f_chmod() and f_utime().
                        -/  (0:Disable or 1:Enable) Also _FS_READONLY needs to be 0 to enable this option. */
                        -
                        -
                        -#define _USE_LABEL		0
                        -/* This option switches volume label functions, f_getlabel() and f_setlabel().
                        -/  (0:Disable or 1:Enable) */
                        -
                        -
                        -#define	_USE_FORWARD	0
                        -/* This option switches f_forward() function. (0:Disable or 1:Enable) */
                        -
                        -
                        -/*---------------------------------------------------------------------------/
                        -/ Locale and Namespace Configurations
                        -/---------------------------------------------------------------------------*/
                        -
                        -#define _CODE_PAGE	932
                        -/* This option specifies the OEM code page to be used on the target system.
                        -/  Incorrect setting of the code page can cause a file open failure.
                        -/
                        -/   1   - ASCII (No extended character. Non-LFN cfg. only)
                        -/   437 - U.S.
                        -/   720 - Arabic
                        -/   737 - Greek
                        -/   771 - KBL
                        -/   775 - Baltic
                        -/   850 - Latin 1
                        -/   852 - Latin 2
                        -/   855 - Cyrillic
                        -/   857 - Turkish
                        -/   860 - Portuguese
                        -/   861 - Icelandic
                        -/   862 - Hebrew
                        -/   863 - Canadian French
                        -/   864 - Arabic
                        -/   865 - Nordic
                        -/   866 - Russian
                        -/   869 - Greek 2
                        -/   932 - Japanese (DBCS)
                        -/   936 - Simplified Chinese (DBCS)
                        -/   949 - Korean (DBCS)
                        -/   950 - Traditional Chinese (DBCS)
                        -*/
                        -
                        -
                        -#define	_USE_LFN	0
                        -#define	_MAX_LFN	255
                        -/* The _USE_LFN switches the support of long file name (LFN).
                        -/
                        -/   0: Disable support of LFN. _MAX_LFN has no effect.
                        -/   1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
                        -/   2: Enable LFN with dynamic working buffer on the STACK.
                        -/   3: Enable LFN with dynamic working buffer on the HEAP.
                        -/
                        -/  To enable the LFN, Unicode handling functions (option/unicode.c) must be added
                        -/  to the project. The working buffer occupies (_MAX_LFN + 1) * 2 bytes and
                        -/  additional 608 bytes at exFAT enabled. _MAX_LFN can be in range from 12 to 255.
                        -/  It should be set 255 to support full featured LFN operations.
                        -/  When use stack for the working buffer, take care on stack overflow. When use heap
                        -/  memory for the working buffer, memory management functions, ff_memalloc() and
                        -/  ff_memfree(), must be added to the project. */
                        -
                        -
                        -#define	_LFN_UNICODE	0
                        -/* This option switches character encoding on the API. (0:ANSI/OEM or 1:UTF-16)
                        -/  To use Unicode string for the path name, enable LFN and set _LFN_UNICODE = 1.
                        -/  This option also affects behavior of string I/O functions. */
                        -
                        -
                        -#define _STRF_ENCODE	3
                        -/* When _LFN_UNICODE == 1, this option selects the character encoding ON THE FILE to
                        -/  be read/written via string I/O functions, f_gets(), f_putc(), f_puts and f_printf().
                        -/
                        -/  0: ANSI/OEM
                        -/  1: UTF-16LE
                        -/  2: UTF-16BE
                        -/  3: UTF-8
                        -/
                        -/  This option has no effect when _LFN_UNICODE == 0. */
                        -
                        -
                        -#define _FS_RPATH	0
                        -/* This option configures support of relative path.
                        -/
                        -/   0: Disable relative path and remove related functions.
                        -/   1: Enable relative path. f_chdir() and f_chdrive() are available.
                        -/   2: f_getcwd() function is available in addition to 1.
                        -*/
                        -
                        -
                        -/*---------------------------------------------------------------------------/
                        -/ Drive/Volume Configurations
                        -/---------------------------------------------------------------------------*/
                        -
                        -#define _VOLUMES	1
                        -/* Number of volumes (logical drives) to be used. */
                        -
                        -
                        -#define _STR_VOLUME_ID	0
                        -#define _VOLUME_STRS	"RAM","NAND","CF","SD","SD2","USB","USB2","USB3"
                        -/* _STR_VOLUME_ID switches string support of volume ID.
                        -/  When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
                        -/  number in the path name. _VOLUME_STRS defines the drive ID strings for each
                        -/  logical drives. Number of items must be equal to _VOLUMES. Valid characters for
                        -/  the drive ID strings are: A-Z and 0-9. */
                        -
                        -
                        -#define	_MULTI_PARTITION	0
                        -/* This option switches support of multi-partition on a physical drive.
                        -/  By default (0), each logical drive number is bound to the same physical drive
                        -/  number and only an FAT volume found on the physical drive will be mounted.
                        -/  When multi-partition is enabled (1), each logical drive number can be bound to
                        -/  arbitrary physical drive and partition listed in the VolToPart[]. Also f_fdisk()
                        -/  funciton will be available. */
                        -
                        -
                        -#define	_MIN_SS		512
                        -#define	_MAX_SS		512
                        -/* These options configure the range of sector size to be supported. (512, 1024,
                        -/  2048 or 4096) Always set both 512 for most systems, all type of memory cards and
                        -/  harddisk. But a larger value may be required for on-board flash memory and some
                        -/  type of optical media. When _MAX_SS is larger than _MIN_SS, FatFs is configured
                        -/  to variable sector size and GET_SECTOR_SIZE command must be implemented to the
                        -/  disk_ioctl() function. */
                        -
                        -
                        -#define	_USE_TRIM	0
                        -/* This option switches support of ATA-TRIM. (0:Disable or 1:Enable)
                        -/  To enable Trim function, also CTRL_TRIM command should be implemented to the
                        -/  disk_ioctl() function. */
                        -
                        -
                        -#define _FS_NOFSINFO	0
                        -/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
                        -/  option, and f_getfree() function at first time after volume mount will force
                        -/  a full FAT scan. Bit 1 controls the use of last allocated cluster number.
                        -/
                        -/  bit0=0: Use free cluster count in the FSINFO if available.
                        -/  bit0=1: Do not trust free cluster count in the FSINFO.
                        -/  bit1=0: Use last allocated cluster number in the FSINFO if available.
                        -/  bit1=1: Do not trust last allocated cluster number in the FSINFO.
                        -*/
                        -
                        -
                        -
                        -/*---------------------------------------------------------------------------/
                        -/ System Configurations
                        -/---------------------------------------------------------------------------*/
                        -
                        -#define	_FS_TINY	0
                        -/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
                        -/  At the tiny configuration, size of the file object (FIL) is reduced _MAX_SS bytes.
                        -/  Instead of private sector buffer eliminated from the file object, common sector
                        -/  buffer in the file system object (FATFS) is used for the file data transfer. */
                        -
                        -
                        -#define _FS_EXFAT	0
                        -/* This option switches support of exFAT file system in addition to the traditional
                        -/  FAT file system. (0:Disable or 1:Enable) To enable exFAT, also LFN must be enabled.
                        -/  Note that enabling exFAT discards C89 compatibility. */
                        -
                        -
                        -#define _FS_NORTC	0
                        -#define _NORTC_MON	1
                        -#define _NORTC_MDAY	1
                        -#define _NORTC_YEAR	2016
                        -/* The option _FS_NORTC switches timestamp functiton. If the system does not have
                        -/  any RTC function or valid timestamp is not needed, set _FS_NORTC = 1 to disable
                        -/  the timestamp function. All objects modified by FatFs will have a fixed timestamp
                        -/  defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR in local time.
                        -/  To enable timestamp function (_FS_NORTC = 0), get_fattime() function need to be
                        -/  added to the project to get current time form real-time clock. _NORTC_MON,
                        -/  _NORTC_MDAY and _NORTC_YEAR have no effect. 
                        -/  These options have no effect at read-only configuration (_FS_READONLY = 1). */
                        -
                        -
                        -#define	_FS_LOCK	0
                        -/* The option _FS_LOCK switches file lock function to control duplicated file open
                        -/  and illegal operation to open objects. This option must be 0 when _FS_READONLY
                        -/  is 1.
                        -/
                        -/  0:  Disable file lock function. To avoid volume corruption, application program
                        -/      should avoid illegal open, remove and rename to the open objects.
                        -/  >0: Enable file lock function. The value defines how many files/sub-directories
                        -/      can be opened simultaneously under file lock control. Note that the file
                        -/      lock control is independent of re-entrancy. */
                        -
                        -
                        -#define _FS_REENTRANT	0
                        -#define _FS_TIMEOUT		1000
                        -#define	_SYNC_t			HANDLE
                        -/* The option _FS_REENTRANT switches the re-entrancy (thread safe) of the FatFs
                        -/  module itself. Note that regardless of this option, file access to different
                        -/  volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
                        -/  and f_fdisk() function, are always not re-entrant. Only file/directory access
                        -/  to the same volume is under control of this function.
                        -/
                        -/   0: Disable re-entrancy. _FS_TIMEOUT and _SYNC_t have no effect.
                        -/   1: Enable re-entrancy. Also user provided synchronization handlers,
                        -/      ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
                        -/      function, must be added to the project. Samples are available in
                        -/      option/syscall.c.
                        -/
                        -/  The _FS_TIMEOUT defines timeout period in unit of time tick.
                        -/  The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
                        -/  SemaphoreHandle_t and etc.. A header file for O/S definitions needs to be
                        -/  included somewhere in the scope of ff.c. */
                        -
                        -
                        -/*--- End of configuration options ---*/
                        diff --git a/firmware/chibios-portapack/ext/fatfs/src/integer.h b/firmware/chibios-portapack/ext/fatfs/src/integer.h
                        index 4660ed62..d8e911cf 100644
                        --- a/firmware/chibios-portapack/ext/fatfs/src/integer.h
                        +++ b/firmware/chibios-portapack/ext/fatfs/src/integer.h
                        @@ -30,7 +30,7 @@ typedef unsigned short	WCHAR;
                         typedef long			LONG;
                         typedef unsigned long	DWORD;
                         
                        -/* This type MUST be 64-bit (Remove this for C89 compatibility) */
                        +/* This type MUST be 64-bit (Remove this for ANSI C (C89) compatibility) */
                         typedef unsigned long long QWORD;
                         
                         #endif
                        
                        LFN構成 at CM3
                        _CODE_PAGE追加コード